OO Mapper 实践(下篇)
上篇介绍了OO Mapper 最核心的映射,简单类型映射,这篇将介绍的复合类型的映射。
1. Dictionary - > Dictionary 字典类型分为:IDictionary,IDictioanry<TKey,TValue>
public class SourceValue { public int Value { get ; set ; } } public class DestValue { public int Value { get ; set ; } } [Test] public void Example() { var sourceDict = new Dictionary< string , SourceValue> { { "First" , new SourceValue {Value = 5}}, { "Second" , new SourceValue {Value = 10}}, { "Third" , new SourceValue {Value = 15}} }; var destDict = Mapper.Map<Dictionary< string , SourceValue>, IDictionary< string , DestValue>>(sourceDict); Assert.AreEqual(3, destDict.Count); Assert.AreEqual(destDict[ "First" ].Value, 5); Assert.AreEqual(destDict[ "Second" ].Value, 10); Assert.AreEqual(destDict[ "Third" ].Value, 15); } [Test] public void Example2() { var sourceDict = new Dictionary< int , SourceValue> { {1, new SourceValue {Value = 5}}, {2, new SourceValue {Value = 10}}, {3, new SourceValue {Value = 15}} }; var destDict = Mapper.Map<Dictionary< int , SourceValue>, IDictionary< string , DestValue>>(sourceDict); Assert.AreEqual(3, destDict.Count); Assert.AreEqual(destDict[ "1" ].Value, 5); Assert.AreEqual(destDict[ "2" ].Value, 10); Assert.AreEqual(destDict[ "3" ].Value, 15); } enum sourceKey { First, Second, Third, } enum destKey { First, Second, Third, } public void Example3() { var sourceDict = new Dictionary<sourceKey, SourceValue> { {sourceKey.First, new SourceValue {Value = 5}}, {sourceKey.Second, new SourceValue {Value = 10}}, {sourceKey.Third, new SourceValue {Value = 15}} }; var destDict = Mapper.Map<Dictionary<sourceKey, SourceValue>, IDictionary<destKey, DestValue>>(sourceDict); Assert.AreEqual(3, destDict.Count); Assert.AreEqual(destDict[destKey.First].Value, 5); Assert.AreEqual(destDict[destKey.Second].Value, 10); Assert.AreEqual(destDict[destKey.Third].Value, 15); } public void Example4() { var sourceDict = new Hashtable() { {1, new SourceValue {Value = 5}}, {2, new SourceValue {Value = 10}}, {3, new SourceValue {Value = 15}} }; var destDict = Mapper.Map<Hashtable, IDictionary< string , DestValue>>(sourceDict); Assert.AreEqual(3, destDict.Count); Assert.AreEqual(destDict[ "1" ].Value, 5); Assert.AreEqual(destDict[ "2" ].Value, 10); Assert.AreEqual(destDict[ "3" ].Value, 15); } public void Example5() { var sourceDict = new Dictionary< int , SourceValue>() { {1, new SourceValue {Value = 5}}, {2, new SourceValue {Value = 10}}, {3, new SourceValue {Value = 15}} }; var destDict = Mapper.Map<Dictionary< int , SourceValue>, Hashtable>(sourceDict); Assert.AreEqual(3, destDict.Count); Assert.AreEqual((destDict[1] as SourceValue).Value, 5); Assert.AreEqual((destDict[2] as SourceValue).Value, 10); Assert.AreEqual((destDict[3] as SourceValue).Value, 15); } |
2. Class -> Dictionary
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public class Person1 { public string Name { get ; set ; } public int Age { get ; set ; } public bool Sex { get ; set ; } } [Test] public void SimpleTest() { var source = new Person1 { Name = "Kevin" , Age = 30, Sex = true }; var dst = Mapper.Map<Person1, IDictionary< string , object >>(source); Assert.AreEqual(dst[ "Name" ], source.Name); Assert.AreEqual(dst[ "Age" ], source.Age); Assert.AreEqual(dst[ "Sex" ], source.Sex); } [Test] public void IgnoreMemberTest() { var source = new Person1 { Name = "Kevin" , Age = 30, Sex = true }; var dst = Mapper .CreateMapper<Person1, IDictionary< string , object >>() .IgnoreSourceMember(x => x.Sex) .Map(source); Assert.AreEqual(dst[ "Name" ], source.Name); Assert.AreEqual(dst[ "Age" ], source.Age); Assert.IsFalse(dst.ContainsKey( "Sex" )); } |
3. Dictionary -> Class 简单转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class TeamSearchCondition { public string BusinessCategory; public string NIROI; public string Lob; [Splite( ',' )] public int [] Product; public string FormName; } [Test] public void Test() { var source = new Dictionary< string , string >(); source[ "BusinessCategory" ] = "kevin" ; source[ "NIROI" ] = "30" ; source[ "Lob" ] = "true" ; source[ "Product" ] = "1,2" ; source[ "FormName" ] = "true" ; var dst = Mapper.Map<IDictionary< string , string >, TeamSearchCondition>(source); Assert.IsNotNull(dst); Assert.IsNotNull(dst.Product != null ); Assert.AreEqual(2, dst.Product.Length); Assert.AreEqual(1, dst.Product[0]); Assert.AreEqual(2, dst.Product[1]); } |
4. Dictioanry -> Class 复杂一点的转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public class Book { public int BookId { get ; set ; } public string BookName { get ; set ; } public Author Author { get ; set ; } public DateTime PublishedDate { get ; set ; } } public class Author { public int AuthorId { get ; set ; } public string AuthorName { get ; set ; } public string Nation { get ; set ; } } [Test] public void TestSubProperty() { var sourceDict = new Dictionary< string , string > { { "BookName" , "设计模式" }, { "Author.AuthorName" , "四人帮" }, { "Author.AuthorId" , "3" } }; var destDict = Mapper.Map<Dictionary< string , string >, Book>(sourceDict); Assert.NotNull(destDict); Assert.AreEqual( "设计模式" , destDict.BookName); Assert.AreEqual( "四人帮" , destDict.Author.AuthorName); Assert.AreEqual(3, destDict.Author.AuthorId); } |
5. DataReader -> List
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | public enum TestClassStatus { First = 0, Second = 1 } class TestClass { public int Id { get ; set ; } public string Name; public TestClassStatus? Status; public Guid Guid; } [Test] public void Test() { var dt = new DataTable(); dt.Columns.Add( new DataColumn( "Id" , typeof ( long ))); dt.Columns.Add( new DataColumn( "Name" , typeof ( string ))); dt.Columns[1].AllowDBNull = true ; dt.Columns.Add( new DataColumn( "Status" , typeof ( long ))); dt.Columns.Add( new DataColumn( "Guid" , typeof (Guid))); int count = 5; for ( int i = 0; i < count; ++i) { if (i%2 == 0) dt.Rows.Add(i, Guid.NewGuid().ToString(), DBNull.Value, Guid.NewGuid()); else dt.Rows.Add(i, DBNull.Value, 1, Guid.NewGuid()); } var reader = dt.CreateDataReader(); var items = Mapper.Map<IDataReader, IEnumerable<TestClass>>(reader); Assert.AreEqual(count, items.Count()); foreach (DataRow row in dt.Rows) { var o1 = row[0]; var o2 = row[1]; var o3 = row[2]; var o4 = row[3]; var i1 = Mapper.Map< object , int >(o1); var i2 = Mapper.Map< object , string >(o2); var i3 = Mapper.Map< object , int >(o3); var i4 = Mapper.Map< object ,Guid>(o4); } } |
6. DataTable -> List (原理是先把DataTable->DataReader->List)
7. List -> DataTable (略)
8. ListSource -> List , List -> ListSource (略)
9. List -> List
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | enum MappingFromStatus { Value1 = 0, Value2 = 1 } class MappingFrom { public int FromID { get ; set ; } public string Name; public int Other; public MappingFromStatus Status; public Guid Guid; } struct MappingTo { public int From_id; public string Name { get ; set ; } public string Other2; public int Status; public Guid Guid; } [Test] public void Test() { var actual = Mapper.Map< string , int >( "12" ); Assert.AreEqual(12, actual); Assert.AreEqual(1, Mapper.Map< int , decimal ?>(1)); var actualArray = Mapper.Map<IList< int >, decimal ?[]>( new List< int > { 1, 2, 3 }); Assert.AreEqual(2, actualArray[1]); var longColl = Mapper.Map< int [], List< long >>( new int [] { 1, 2, 3 }); Assert.AreEqual(2, longColl[1]); var doubleArray = Mapper.Map<List< string >, double []>( new List< string > { "1.1" , "2.2" , "3.3" }); Assert.AreEqual(2.2, doubleArray[1]); Mapper .CreateMapper<MappingFrom, MappingTo>() .IgnoreCase( true ) .IgnoreUnderscore( true ) .IgnoreSourceMember(x => x.Guid); var guid = Guid.NewGuid(); var customFrom = new MappingFrom { FromID = 1, Name = "name" , Status = MappingFromStatus.Value2, Guid = guid }; var customTo = Mapper.Map<MappingFrom, MappingTo>(customFrom); Assert.AreEqual(1, customTo.From_id); Assert.AreEqual( "name" , customTo.Name); Assert.IsNullOrEmpty(customTo.Other2); Assert.AreEqual(1, customTo.Status); Assert.AreNotEqual(guid, customTo.Guid); |
10. Class -> Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | public class ModelObject { public DateTime BaseDate { get ; set ; } public ModelSubObject Sub { get ; set ; } public ModelSubObject Sub2 { get ; set ; } public ModelSubObject SubWithExtraName { get ; set ; } } public class ModelSubObject { public string ProperName { get ; set ; } public ModelSubSubObject SubSub { get ; set ; } } public class ModelSubSubObject { public string IAmACoolProperty { get ; set ; } } public class ModelDto { public DateTime BaseDate { get ; set ; } public string SubProperName { get ; set ; } public string Sub2ProperName { get ; set ; } public string SubWithExtraNameProperName { get ; set ; } public string SubSubSubIAmACoolProperty { get ; set ; } } [Test] public void TestFlattering() { var source = new ModelObject { BaseDate = DateTime.Now, Sub = new ModelSubObject { ProperName = "Some name" , SubSub = new ModelSubSubObject { IAmACoolProperty = "Cool daddy-o" } }, Sub2 = new ModelSubObject { ProperName = "Sub 2 name" }, SubWithExtraName = new ModelSubObject { ProperName = "Some other name" }, }; var b =Mapper.Map<ModelObject, ModelDto>(source); Assert.AreEqual(source.BaseDate, b.BaseDate); Assert.AreEqual(source.Sub.ProperName, b.SubProperName); Assert.AreEqual(source.Sub2.ProperName, b.Sub2ProperName); Assert.AreEqual(source.SubWithExtraName.ProperName, b.SubWithExtraNameProperName); Assert.AreEqual(source.Sub.SubSub.IAmACoolProperty, b.SubSubSubIAmACoolProperty); } |
完。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!