Green.AgileMapper開源項目的使用(1)


       在架構設計中,利用領域驅動開發時,涉及到do(領域對象)和dto(數據傳輸對象)的相互裝換匹配,這段代碼簡單但是重復頻率太多,寫得我很冒火(我有個職責是wcf SOA包裝),我是個不喜歡重復勞動的懶人,我在網上搜索等到很多實體匹配的框架EmitMapper,AutoMapper等,但是他們都不能滿足dto和do的對象的按規則匹配包裝。最后我只得花了半個小時寫了一個簡單的代碼生成器,完成了我的任務。但是事后總覺得不爽,於是有了寫下這個AgileMapper框架來適應領域開發中的po,do,dto,vo着一些列對象的相互包裝,建立一個按規則包裝的Mapper框架。項目已經完成上傳於CodePlex http://agilemapper.codeplex.com/ ,目前剛成型,希望大家能夠幫助測試,提出bug,或者修復。我不是很清楚開源協議,選擇了一個 協議。大家可以隨便使用和修改應用來滿足各自的需求,但是如果有些bug修復或者好的通用的修改希望大家能夠,提交供我和其他人學習共同進步,但是這不是必須的,你也可以選擇保留。

       AgileMapper架構設計類圖:

AgileMapper

    在AgileMapper中支持多種MappingConfigurator(匹配管理器)都集成至MappingConfiguratorBase(MappingConfiguratorBase中擁有唯一的對象之間對於相等的默認表達式守信,針對於dto轉化為do對象級聯刪除情況),內置了AttributeMappingConfigurator,XMLMappingConfigurator,DataRowMappingConfigurator三種匹配管理器。支持xml書寫,attribute標記規則。由這些管理器根據具體標記標記方式產生一組IMappingRule(匹配規則),內置了5中匹配規則(簡單,集合,表達式,對象,datarow)。

   在AgileMapper為我們提供了MappingConfiguratorBase的擴展,IMappingRule的擴展,已經多余Attribute標注的擴展CustomerMappingAttribute,已經xml的配置擴展。

下面我們來使用AgileMapper提供的內置Mapper。

測試預備:

Domain Object:

View Code
public  class StudenDo 
   { 
        public  int ID 
       { 
            get
            set
       } 

        public  string Name 
       {  getset; } 

        public Sex Sex 
       {  getset; } 

        public Address Address 
       {  getset; } 

        public ContactWay ContactWay 
       {  getset; } 

        public List< string> CourseIds 
       {  getset; } 

        public List<KeyValuePair> Propertys 
       {  getset; } 

   } 

    public  class KeyValuePair 
   { 
        public  string Key 
       {  getset; } 

        public  string Value 
       {  getset; } 
   } 

    public  enum Sex 
   { 
       男, 女 
   }

 

public  class ContactWay 
   { 
       public  string Phone 
      { 
           get
           set
      } 

       public  string Email 
      { 
           get
           set
      } 

       public  string QQ 
      { 
           get
           set
      } 
   }

 

 

public  class Address 
   { 
        public  string Country 
       { 
            get
            set
       } 

        public  string Province 
       {  getset; } 

        public  string Street 
       {  getset; } 

        public  string Particular 
       {  getset; } 
   }

 

Dto:

View Code
  

public  class StudenDto 
   { 
        public  int ID 
       { 
            get
            set
       } 

        public  string Name 
       {  getset; } 

        public Sex Sex 
       {  getset; } 

       [Mapping( " Address.Country ")] 
        public  string Country 
       { 
            get
            set
       } 

       [Mapping( " Address.Province ")] 
        public  string Province 
       {  getset; } 

        //  [Mapping("Address.Street")] 
       [IgnoreMapping] 
        public  string Street 
       {  getset; } 

       [ExpressionMapping( " Address.Country +\" 國籍 \"+Address.Province +\" 省 \" ")] 
        public  string Particular 
       {  getset; } 

       [ObjectMappingAttribute] 
        public ContactWayDto ContactWay 
       {  getset; } 

       [CollectionMapping()] 
        public List< string> CourseIds 
       {  getset; } 

       [CollectionMapping(EqualExpression= " from.Key==to.Key ",IsDeleteNotInFromItem= true)] 
        public List<KeyValuePair> Propertys 
       {  getset; } 

       [ExpressionMapping( " Propertys[0].Key ")] 
        public  string FirstPropertyKey 
       { 
            get
            set
       } 

 

public  class ContactWayDto 
    { 
         public  string Phone 
        { 
             get
             set
        } 

         public  string Email 
        { 
             get
             set
        } 

         public  string QQ 
        { 
             get
             set
        } 
    }

public  class AddressDto 

     public  string Country 
    { 
         get
         set
    } 

     public  string Province 
    {  getset; } 

     public  string Street 
    {  getset; } 

     public  string Particular 
    {  getset; } 
}

 

一:Attribute標注:

View Code
  

[TestMethod] 
        public  void AttributeConfig_SimpleMapping_Gen() 
       { 

           StudenDo stu =  new StudenDo() 
           { 
               ID =  1
               Name =  " test1 "
               Sex = Sex.女, 
               Address =  new Address() 
               { 
                   Country =  " 中國 "
                   Province =  " 四川 "
                   Street =  " 高新區 " 
               }, 
               CourseIds =  new List< string>() {  " 1 "" 2 "" 3 " }, 
               Propertys =  new List<KeyValuePair>() {  new KeyValuePair() { Key =  " 1 ", Value =  " 1 " } }, 
               ContactWay =  new ContactWay() 
               { 
                   Phone =  " 1111111111111111 "
                   Email =  " xxxx@12f "
                   QQ =  " 7889789999889 " 
               } 
           }; 

            var mapper = ObjectMapperManager.Default.GetMapper<StudenDto, StudenDo>(); 

            var dt1 = DateTime.Now; 
            var stuDto = mapper.Warp(stu); 
            var sp = DateTime.Now - dt1; 

           dt1 = DateTime.Now; 
           stuDto = mapper.Warp(stu); 
            var sp1 = DateTime.Now - dt1; 

           Assert.AreEqual(stuDto.ID, stu.ID); 
           Assert.AreEqual(stuDto.Name, stu.Name); 
           Assert.AreEqual(stuDto.Sex, stu.Sex); 
           Assert.AreEqual(stuDto.Country, stu.Address.Country); 
           Assert.AreEqual(stuDto.Province, stu.Address.Province); 
           Assert.AreEqual(stuDto.Street,  null); // Ignore 
           
// object 
           
//  Assert.AreEqual(stuDto.ContactWay,null); 
           Assert.AreEqual(stuDto.ContactWay.QQ, stu.ContactWay.QQ); 
           Assert.AreEqual(stuDto.ContactWay.Email, stu.ContactWay.Email); 
            // expression 
           Assert.AreEqual(stuDto.Particular,  string.Format( " {0} 國籍 {1} 省  ", stu.Address.Country, stu.Address.Province)); 
           Assert.AreEqual(stuDto.FirstPropertyKey, stu.Propertys[ 0].Key); 
            // collection            
           Assert.AreEqual(stuDto.CourseIds[ 0], stu.CourseIds[ 0]); 
           Assert.AreEqual(stuDto.CourseIds.Count, stu.CourseIds.Count); 

           Assert.AreEqual(stuDto.Propertys[ 0].Key, stu.Propertys[ 0].Key); 
           Assert.AreEqual(stuDto.Propertys[ 0].Value, stu.Propertys[ 0].Value); 
           Assert.AreEqual(stuDto.Propertys.Count, stu.Propertys.Count); 

            // Warp 2 
            var stuDo =  new StudenDo(); 
           mapper.Warp(stuDto, stuDo); 

           Assert.AreEqual(stuDo.ID, stuDto.ID); 
           Assert.AreEqual(stuDo.Name, stuDto.Name); 
           Assert.AreEqual(stuDo.Sex, stuDto.Sex); 
           Assert.AreEqual(stuDo.Address.Country, stuDto.Country); 
           Assert.AreEqual(stuDo.Address.Province, stuDto.Province); 
            // Assert.AreEqual(stuDo.Address.Street, null); // Ignore 
           
// object 
           Assert.AreEqual(stuDo.ContactWay.QQ, stuDto.ContactWay.QQ); 
           Assert.AreEqual(stuDo.ContactWay.Email, stuDto.ContactWay.Email); 
            // collection 

           Assert.AreEqual(stuDo.CourseIds.Count, stuDto.CourseIds.Count); 
           Assert.AreEqual(stuDo.CourseIds[ 0], stuDto.CourseIds[ 0]); 

           Assert.AreEqual(stuDo.Propertys.Count, stuDto.Propertys.Count); 
           Assert.AreEqual(stuDo.Propertys[ 0].Key, stuDto.Propertys[ 0].Key); 
           Assert.AreEqual(stuDo.Propertys[ 0].Value, stuDto.Propertys[ 0].Value); 
       } 

       [TestMethod] 
        public  void AttributeConfig_SimpleMapping() 
       { 
           StudenDo stu =  new StudenDo() 
           { 
               ID =  1
               Name =  " test1 "
               Sex = Sex.女, 
               Address =  new Address() 
               { 
                   Country =  " 中國 "
                   Province =  " 四川 "
                   Street =  " 高新區 " 
               }, 
               CourseIds =  new List< string>() {  " 1 "" 2 "" 3 " }, 
               Propertys =  new List<KeyValuePair>() {  new KeyValuePair() { Key =  " 1 ", Value =  " 1 " } }, 
               ContactWay =  new ContactWay() 
               { 
                   Phone =  " 1111111111111111 "
                   Email =  " xxxx@12f "
                   QQ =  " 7889789999889 " 
               } 
           }; 

            var mapper = ObjectMapperManager.Default.GetMapper(); 
            var stuDto = mapper.Warp( typeof(StudenDto), stu)  as StudenDto; 

           Assert.AreEqual(stuDto.ID, stu.ID); 
           Assert.AreEqual(stuDto.Name, stu.Name); 
           Assert.AreEqual(stuDto.Sex, stu.Sex); 
           Assert.AreEqual(stuDto.Country, stu.Address.Country); 
           Assert.AreEqual(stuDto.Province, stu.Address.Province); 
           Assert.AreEqual(stuDto.Street,  null); // Ignore 
           
// object 
           Assert.AreEqual(stuDto.ContactWay.QQ, stu.ContactWay.QQ); 
           Assert.AreEqual(stuDto.ContactWay.Email, stu.ContactWay.Email); 
            // expression 
           Assert.AreEqual(stuDto.Particular,  string.Format( " {0} 國籍 {1} 省  ", stu.Address.Country, stu.Address.Province)); 
            // collection            
           Assert.AreEqual(stuDto.CourseIds[ 0], stu.CourseIds[ 0]); 
           Assert.AreEqual(stuDto.CourseIds.Count, stu.CourseIds.Count); 
       } 

二:xml配置標注規則: 

View Code
<? xml version="1.0" encoding="utf-8"  ?> 
< AgileMapper > 
   < Extensions > 
     < Extension  Name ="SimpleMappingRule"  Type ="Green.AgileMapper.SimpleMappingRule,Green.AgileMapper" ></ Extension > 
     < Extension  Name ="ObjectMappingRule"  Type ="Green.AgileMapper.ObjectMappingRule,Green.AgileMapper" ></ Extension > 
     < Extension  Name ="CollectionMappingRule"  Type ="Green.AgileMapper.CollectionMappingRule,Green.AgileMapper" ></ Extension > 
     < Extension  Name ="ExpressionMappingRule"  Type ="Green.AgileMapper.ExpressionMappingRule,Green.AgileMapper" ></ Extension > 
   </ Extensions > 
   < Mappings > 
     < Mapping  FromType ="AgileMapper.Test.StudenDto,AgileMapper.Test"    > 
       < SimpleMappingRule  FromPoperty ="Country"  ToPoperty ="Address.Country" ></ SimpleMappingRule > 
       < SimpleMappingRule  FromPoperty ="Province"  ToPoperty ="Address.Province" ></ SimpleMappingRule >           
       < ObjectMappingRule   FromPoperty ="ContactWay"  ToPoperty ="ContactWay" ></ ObjectMappingRule > 
       < CollectionMappingRule  FromPoperty ="CourseIds"  ToPoperty ="CourseIds" ></ CollectionMappingRule > 
       < CollectionMappingRule  FromPoperty ="Propertys"  ToPoperty ="Propertys"  EqualExpression ="from.Key==to.Key"  IsDeleteNotInFromItem ="true" ></ CollectionMappingRule > 
       < ExpressionMappingRule   FromPoperty ="Particular"  Expression ="Address.Country +Address.Province" ></ ExpressionMappingRule > 
       < ExpressionMappingRule   FromPoperty ="FirstPropertyKey"  Expression ="Propertys[0].Key" ></ ExpressionMappingRule > 
       < Ignores > 
         < Ignore  Name ="Street" ></ Ignore > 
       </ Ignores > 
     </ Mapping > 
   </ Mappings > 
</ AgileMapper >

測試代碼:

View Code
  

[TestMethod] 
         public  void XMlConfig_SimpleMapping_Gen() 
        { 

            StudenDo stu =  new StudenDo() 
            { 
                ID =  1
                Name =  " test1 "
                Sex = Sex.女, 
                Address =  new Address() 
                { 
                    Country =  " 中國 "
                    Province =  " 四川 "
                    Street =  " 高新區 " 
                }, 
                CourseIds =  new List< string>() {  " 1 "" 2 "" 3 " }, 
                Propertys =  new List<KeyValuePair>() {  new KeyValuePair() { Key =  " 1 ", Value =  " 1 " } }, 
                ContactWay =  new ContactWay() 
                { 
                    Phone =  " 1111111111111111 "
                    Email =  " xxxx@12f "
                    QQ =  " 7889789999889 " 
                } 
            }; 

             var mapper = ObjectMapperManager.Default.GetMapper<StudenDto, StudenDo>( new XMLMappingConfigurator( @" E:\Project\OpenSource\AgileMapper\AgileMappper.Test\XMLConfigurator\AgileMapper.xml ")); 

             var stuDto = mapper.Warp(stu);           

            Assert.AreEqual(stuDto.ID, stu.ID); 
            Assert.AreEqual(stuDto.Name, stu.Name); 
            Assert.AreEqual(stuDto.Sex, stu.Sex); 
            Assert.AreEqual(stuDto.Country, stu.Address.Country); 
            Assert.AreEqual(stuDto.Province, stu.Address.Province); 
            Assert.AreEqual(stuDto.Street,  null); // Ignore 
            
// object 
            
//  Assert.AreEqual(stuDto.ContactWay,null); 
            Assert.AreEqual(stuDto.ContactWay.QQ, stu.ContactWay.QQ); 
            Assert.AreEqual(stuDto.ContactWay.Email, stu.ContactWay.Email); 
             // expression 
            Assert.AreEqual(stuDto.Particular.Replace( "   """),  string.Format( " {0}{1} ", stu.Address.Country, stu.Address.Province)); 
            Assert.AreEqual(stuDto.FirstPropertyKey, stu.Propertys[ 0].Key); 
             // collection            
            Assert.AreEqual(stuDto.CourseIds[ 0], stu.CourseIds[ 0]); 
            Assert.AreEqual(stuDto.CourseIds.Count, stu.CourseIds.Count); 

            Assert.AreEqual(stuDto.Propertys[ 0].Key, stu.Propertys[ 0].Key); 
            Assert.AreEqual(stuDto.Propertys[ 0].Value, stu.Propertys[ 0].Value); 
            Assert.AreEqual(stuDto.Propertys.Count, stu.Propertys.Count); 

             // Warp 2 
             var stuDo =  new StudenDo(); 
            mapper.Warp(stuDto, stuDo); 

            Assert.AreEqual(stuDo.ID, stuDto.ID); 
            Assert.AreEqual(stuDo.Name, stuDto.Name); 
            Assert.AreEqual(stuDo.Sex, stuDto.Sex); 
            Assert.AreEqual(stuDo.Address.Country, stuDto.Country); 
            Assert.AreEqual(stuDo.Address.Province, stuDto.Province); 
             // Assert.AreEqual(stuDo.Address.Street, null); // Ignore 
            
// object 
            Assert.AreEqual(stuDo.ContactWay.QQ, stuDto.ContactWay.QQ); 
            Assert.AreEqual(stuDo.ContactWay.Email, stuDto.ContactWay.Email); 
             // collection 

            Assert.AreEqual(stuDo.CourseIds.Count, stuDto.CourseIds.Count); 
            Assert.AreEqual(stuDo.CourseIds[ 0], stuDto.CourseIds[ 0]); 

            Assert.AreEqual(stuDo.Propertys.Count, stuDto.Propertys.Count); 
            Assert.AreEqual(stuDo.Propertys[ 0].Key, stuDto.Propertys[ 0].Key); 
            Assert.AreEqual(stuDo.Propertys[ 0].Value, stuDto.Propertys[ 0].Value); 
        }

三:DataRow的測試: 

測試預備StudentModelForDataRow:

View Code
public  class StudentModelForDataRow 
    { 
         public  int ID 
        {  getset; } 

         public  string Name 
        {  getset; } 
    }

測試代碼: 

View Code
[TestMethod] 
        public  void DataRowConfig_SameTable_DataRowCloneMapping() 
       { 
           DataTable dt =  new DataTable(); 
           dt.Columns.AddRange( new DataColumn[] { 
                new DataColumn( " ID ", typeof( int)), 
                new DataColumn( " Name ", typeof( string)) 
           }); 

            var row = dt.NewRow(); 
           row[ 0] =  1
           row[ 1] =  " Green "
           dt.Rows.Add(row); 

            var rowClone = dt.NewRow(); 

            var mapper = ObjectMapperManager.Default.GetMapper( new DataRowMappingConfigurator()); 
           mapper.Warp( typeof(DataRow), row, rowClone); 
           Assert.AreEqual(row[ 0], rowClone[ 0]); 
           Assert.AreEqual(row[ 1], rowClone[ 1]); 
       } 

       [TestMethod] 
        public  void DataRowConfig_UnSameTable_MutipleRule_DataRowCloneMapping() 
       { 
           DataTable dt =  new DataTable(); 
           dt.Columns.AddRange( new DataColumn[] { 
                new DataColumn( " ID ", typeof( int)), 
                new DataColumn( " Name ", typeof( string)) 
           }); 

           DataTable dt2 =  new DataTable(); 
           dt2.Columns.AddRange( new DataColumn[] { 
                new DataColumn( " ID ", typeof( int)), 
                new DataColumn( " Name ", typeof( string)), 
                 new DataColumn( " Sex ", typeof( string)) 
           }); 

            var row = dt2.NewRow(); 
           row[ 0] =  1
           row[ 1] =  " Green "
           row[ 2] =  " Nan "
           dt2.Rows.Add(row); 

            var rowClone = dt.NewRow(); 

            var mapper = ObjectMapperManager.Default.GetMapper( new DataRowMappingConfigurator()); 
           mapper.Warp(row, rowClone); 
           Assert.AreEqual(row[ 0], rowClone[ 0]); 
           Assert.AreEqual(row[ 1], rowClone[ 1]); 
       } 

       [TestMethod] 
        public  void DataRowConfig_UnSameTable_Not_MutipleRule_DataRowCloneMapping() 
       { 
           DataTable dt =  new DataTable(); 
           dt.Columns.AddRange( new DataColumn[] { 
                new DataColumn( " ID ", typeof( int)), 
                new DataColumn( " Name ", typeof( string)) 
           }); 

           DataTable dt2 =  new DataTable(); 
           dt2.Columns.AddRange( new DataColumn[] { 
                new DataColumn( " ID ", typeof( int)), 
                new DataColumn( " Name ", typeof( string)), 
                 new DataColumn( " Sex ", typeof( string)) 
           }); 

            var row = dt.NewRow(); 
           row[ 0] =  1
           row[ 1] =  " Green "
           dt.Rows.Add(row); 

            var rowClone = dt2.NewRow(); 

            var mapper = ObjectMapperManager.Default.GetMapper( new DataRowMappingConfigurator()); 
           mapper.Warp(row, rowClone); 
           Assert.AreEqual(row[ 0], rowClone[ 0]); 
           Assert.AreEqual(row[ 1], rowClone[ 1]); 
       } 

       [TestMethod] 
        public  void DataRowConfig_To_Object_CloneMapping() 
       { 
           DataTable dt =  new DataTable(); 
           dt.Columns.AddRange( new DataColumn[] { 
                new DataColumn( " ID ", typeof( int)), 
                new DataColumn( " Name ", typeof( string)) 
           }); 

            var row = dt.NewRow(); 
           row[ 0] =  1
           row[ 1] =  " Green "
           dt.Rows.Add(row); 
           StudentModelForDataRow model =  new StudentModelForDataRow(); 

            var mapper = ObjectMapperManager.Default.GetMapper( new DataRowMappingConfigurator()); 
           mapper.Warp(row, model); 
           Assert.AreEqual(model.ID, row[ 0]); 
           Assert.AreEqual(model.Name, row[ 1]); 
       }

     DataRow匹配針對相同的表結構和不同表結構,以及實體類和DataRow之間的轉化。 

單元測試結果:

QQ截圖未命名

     對於xml配置的架構還沒做,以及基於T4模板的按照規則代碼生成模板還在進一步開發中,敬請期待。

     今天就寫在這里了,歡迎大家的指正和修改,希望你的修改如果更好能通知我,給我好的建議和探討,謝謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM