定义的接口IObjectMapper,和默认的实现类DefaultObjectMapper
其中AutoMapperObjectMapper是替换实现
/// <summary> /// Defines a simple interface to automatically map objects. /// </summary> public interface IObjectMapper { /// <summary> /// Converts an object to another. Creates a new object of <see cref="TDestination"/>. /// </summary> /// <typeparam name="TDestination">Type of the destination object</typeparam> /// <typeparam name="TSource">Type of the source object</typeparam> /// <param name="source">Source object</param> TDestination Map<TSource, TDestination>(TSource source); /// <summary> /// Execute a mapping from the source object to the existing destination object /// </summary> /// <typeparam name="TSource">Source type</typeparam> /// <typeparam name="TDestination">Destination type</typeparam> /// <param name="source">Source object</param> /// <param name="destination">Destination object</param> /// <returns>Returns the same <see cref="destination"/> object after mapping operation</returns> TDestination Map<TSource, TDestination>(TSource source, TDestination destination); } /// <summary> /// Maps an object to another. /// Implement this interface to override object to object mapping for specific types. /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TDestination"></typeparam> public interface IObjectMapper<in TSource, TDestination> { /// <summary> /// Converts an object to another. Creates a new object of <see cref="TDestination"/>. /// </summary> /// <param name="source">Source object</param> TDestination Map(TSource source); /// <summary> /// Execute a mapping from the source object to the existing destination object /// </summary> /// <param name="source">Source object</param> /// <param name="destination">Destination object</param> /// <returns>Returns the same <see cref="destination"/> object after mapping operation</returns> TDestination Map(TSource source, TDestination destination); }
2、AutoMapper
AutoMapper是一个对象与对象的映射器
首先,您需要使用源类型和目标类型。目标类型的设计可能会受到其所在层的影响,但只要成员的名称与源类型的成员相匹配,AutoMapper就可以发挥最佳效果
您现在必须使用Mapper.Initialize
或new MapperConfiguration()
来初始化AutoMapper
。如果您希望保持静态使用,请使用Mapper.Initialize
。
如果你有很多的Mapper.CreateMap
调用,把它们移动到一个Profile
,或者Mapper.Initialize
,在启动时调用一次。
Mapper.Initialize(cfg => cfg.CreateMap<Order, OrderDto>()); //or var config = new MapperConfiguration(cfg => cfg.CreateMap<Order, OrderDto>());
定义属性
1、AutoMapAttribute,双向映射
如 [AutoMap(typeof(MyClass2), typeof(MyClass3))] private class MyClass1
foreach (var targetType in TargetTypes) { configuration.CreateMap(type, targetType, MemberList.Source); configuration.CreateMap(targetType, type, MemberList.Destination); }
2、AutoMapFromAttribute
如:[AutoMapFrom(typeof(MyClass3))] 即MyClass3就目标类型
foreach (var targetType in TargetTypes) { configuration.CreateMap(targetType, type, MemberList); }
3、 AutoMapToAttribute
如:[AutoMapTo(typeof(MyClass3))] private class MyClass2 即MyClass3是目标类型,而MyClass2是源类型
foreach (var targetType in TargetTypes) { configuration.CreateMap(type, targetType, MemberList); }
上述的应用,在模块的应用初始化前OnPreApplicationInitialization,实行操作CreateMap操作
1、首先初始化类型查找器ITypeFinder
2、查找相关的属性数组
var types = typeFinder.Types.Where(type => { var typeInfo = type.GetTypeInfo(); return typeInfo.IsDefined(typeof(AutoMapAttribute)) || typeInfo.IsDefined(typeof(AutoMapFromAttribute)) || typeInfo.IsDefined(typeof(AutoMapToAttribute)); } ).ToArray();
在上下文里IAbpAutoMapperConfigurationContext,属性IMapperConfigurationExpression,执行上述的CreateMap的操作
public static void CreateAutoAttributeMaps(this IMapperConfigurationExpression configuration, Type type) { foreach (var autoMapAttribute in type.GetTypeInfo().GetCustomAttributes<AutoMapAttributeBase>()) { autoMapAttribute.CreateMap(configuration, type); } }
二、对Profile的配置
void ConfigureAll(IAbpAutoMapperConfigurationContext ctx) { FindAndAutoMapTypes(ctx); //针对属性进行配置 foreach (var configurator in options.Configurators) //针对profile进行配置 { configurator(ctx); } } void ValidateAll(IConfigurationProvider config) { foreach (var profileType in options.ValidatingProfiles) { config.AssertConfigurationIsValid(((Profile)Activator.CreateInstance(profileType)).ProfileName); } }
重点看AbpAutoMapperOptions的AddProfile方法,这里面在模块设置里进行配置
手写映射配置代码虽然繁琐,但具有可测试的优点。AutoMapper
背后的设计灵感之一是不仅消除了自定义映射代码,而且消除了手动测试的需要。由于从源到目标的映射是基于约定的,因此您仍需要测试配置
public void AddProfile<TProfile>(bool validate = false) where TProfile: Profile, new() { Configurators.Add(context => { context.MapperConfiguration.AddProfile<TProfile>(); }); if (validate) { ValidatingProfiles.Add<TProfile>(); } }
三、使用例子
模块的使用进行配置
public override void ConfigureServices(ServiceConfigurationContext context) { Configure<AbpAutoMapperOptions>(options => { options.UseStaticMapper = false; options.AddProfile<ValidatedProfile>(true); options.AddProfile<NonValidatedProfile>(); }); }
手写映射配置代码虽然繁琐,但具有可测试的优点。AutoMapper
背后的设计灵感之一是不仅消除了自定义映射代码,而且消除了手动测试的需要。由于从源到目标的映射是基于约定的,因此您仍需要测试配置
作者:慕姐8265434
链接:http://www.imooc.com/article/273854?block_id=tuijian_wz
来源:慕课网
原文:https://www.cnblogs.com/cloudsu/p/11231033.html