快速指导
public class A { public string message; } public class B { public string message = "Hello, world!!!" ; } |
现在,我们有一个实体类B,我们想把它转为实体类A,但是又不想手动字段赋值。可以用以下方式解决:
B b = new B(); A a = ObjectMapperManager.DefaultInstance.GetMapper<B, A>().Map(b); |
这个类库最主要的类是ObjectMapperManager。这个类实现了对象映射(在IL运行时)和映射缓存
/// <summary> /// 用于维护和生成映射的类 /// </summary> public class ObjectMapperManager { public static ObjectMapperManager DefaultInstance public ObjectMapperManager(); /// <summary> /// 返回特定类型的映射实体 /// </summary> /// <typeparam name="TFrom">来源类型</typeparam> /// <typeparam name="TTo">映射类型</typeparam> /// <returns></returns> public ObjectsMapper<TFrom, TTo> GetMapper<TFrom, TTo>(); /// <summary> /// 返回特定类型的映射实体 /// </summary> /// <typeparam name="TFrom">来源类型</typeparam> /// <typeparam name="TTo">映射类型</typeparam> /// <param name="ShallowCopy">True, 如果来源类型和映射类型中的某字段是引用类型,且类型相同,映射时,会直接引用而不会创建新的对象</param> /// <returns></returns> public ObjectsMapper<TFrom, TTo> GetMapper<TFrom, TTo>( bool ShallowCopy); /// <summary> /// 返回特定类型的映射实体 /// </summary> /// <typeparam name="TFrom">来源类型</typeparam> /// <typeparam name="TTo">映射类型</typeparam> /// <param name="ShallowCopy">True, 如果来源类型和映射类型中的某字段是引用类型,且类型相同,映射时,会直接引用而不会创建新的对象</param> /// <param name="mappingConfigurator">映射配置委托</param> /// <param name="mapperName">映射实体的名称。如果两个映射实体有相同的参数,但是名称不一样,那么,将生成两个不同的映射实体</param> /// <returns></returns> public ObjectsMapper<TFrom, TTo> GetMapper<TFrom, TTo>( bool ShallowCopy, MappingConfigurator mappingConfigurator, string mapperName); /// <summary> /// 返回特定类型的映射实现实体 /// </summary> /// <param name="from">来源类型</param> /// <param name="to">映射类型</param> /// <param name="ShallowCopy">True, 如果来源类型和映射类型中的某字段是引用类型,且类型相同,映射时,会直接引用而不会创建新的对象</param> /// <param name="mappingConfigurator">映射配置委托</param> /// <returns></returns> public ObjectsMapperBaseImpl GetMapperImpl( Type from, Type to, bool ShallowCopy, MappingConfigurator mappingConfigurator); /// <summary> /// 返回特定类型的映射实现实体 /// </summary> /// <param name="from">来源类型</param> /// <param name="to">映射类型</param> /// <param name="ShallowCopy">True, 如果来源类型和映射类型中的某字段是引用类型,且类型相同,映射时,会直接引用而不会创建新的对象</param> /// <param name="mappingConfigurator">映射配置委托</param> /// <param name="mapperName">映射实现实体的名称。如果两个映射实现实体有相同的参数,但是名称不一样,那么,将生成两个不同的映射实现实体</param> /// <returns></returns> public ObjectsMapperBaseImpl GetMapperImpl( Type from, Type to, bool ShallowCopy, MappingConfigurator mappingConfigurator, string mapperName); } |
一般情况下,如果你不需要分离映射缓存,你能够使用线程安全的 ObjectMapperManager.DefaultInstance 对象,你不需要实例化ObjectMapperManager
使用类ObjectMapperManager你能够创建ObjectsMapper实体,用于实体映射操作
public class ObjectsMapper<TFrom, TTo> { public TTo Map(TFrom from, TTo to); public TTo Map(TFrom from); } |
使用这种方案,需要以下两步:
Step 1: 使用类ObjectMapperManager创建一个ObjectsMapper:
var mapper = ObjectMapperManager.DefaultInstance.GetMapper<B, A>(); |
Step 2: 使用上一步创建的mapper来映射对象
A a = mapper.Map( new B()); |
比如,我们有两个类“A”和“B”,他们有相同的结构
public class A { public enum En { En1, En2, En3 } public class AInt { internal int intern = 13; public string str = "AInt" ; public AInt() { intern = 13; } } private string m_str1 = "A::str1" ; public string str1 { get { return m_str1; } set { m_str1 = value; } } public string str2 = "A::str2" ; public AInt obj; public En en = En.En3; int [] m_arr; public int [] arr { set { m_arr = value; } get { return m_arr; } } public AInt[] objArr; public string str3 = "A::str3" ; public A() { Console.WriteLine( "A::A()" ); } } public class B { public enum En { En1, En2, En3 } public class BInt { public string str = "BInt" ; } public string str1 = "B::str1" ; public string str2 { get { return "B::str2" ; } } public BInt obj = new BInt(); public En en = En.En2; public BInt[] objArr; public int [] arr { get { return new int [] { 1, 5, 9 }; } } public object str3 = null ; public B() { Console.WriteLine( "B::B()" ); objArr = new BInt[2]; objArr[0] = new BInt(); objArr[0].str = "b objArr 1" ; objArr[1] = new BInt(); objArr[1].str = "b objArr 2" ; } } |
将类B映射到类A:
A a = new A(); B b = new B(); ObjectMapperManager.DefaultInstance.GetMapper<B, A>().Map(b, a); Assert.AreEqual(a.en, A.En.En2); Assert.AreEqual(a.str1, b.str1); Assert.AreEqual(a.str2, b.str2); Assert.AreEqual(a.obj.str, b.obj.str); Assert.AreEqual(a.obj.intern, 13); Assert.AreEqual(a.arr.Length, b.arr.Length); Assert.AreEqual(a.arr[0], b.arr[0]); Assert.AreEqual(a.arr[1], b.arr[1]); Assert.AreEqual(a.arr[2], b.arr[2]); Assert.AreEqual(a.objArr.Length, b.objArr.Length); Assert.AreEqual(a.objArr[0].str, b.objArr[0].str); Assert.AreEqual(a.objArr[1].str, b.objArr[1].str); Assert.IsNull(a.str3); |