auto mapper
社区开源库 AutoMapper 提供的映射核心代码 IMapperBase-->IMapper-->Mapper
namespace AutoMapper;
public interface IMapperBase
{
TDestination Map<TDestination>(object source);
TDestination Map<TSource, TDestination>(TSource source);
TDestination Map<TSource, TDestination>(TSource source, TDestination destination);
object Map(object source, Type sourceType, Type destinationType);
object Map(object source, object destination, Type sourceType, Type destinationType);
}
public interface IMapper : IMapperBase
{
TDestination Map<TDestination>(
object source,
Action<IMappingOperationOptions<object, TDestination>> opts);
TDestination Map<TSource, TDestination>(
TSource source,
Action<IMappingOperationOptions<TSource, TDestination>> opts);
TDestination Map<TSource, TDestination>(
TSource source,
TDestination destination,
Action<IMappingOperationOptions<TSource, TDestination>> opts);
object Map(
object source,
Type sourceType,
Type destinationType,
Action<IMappingOperationOptions<object, object>> opts);
object Map(
object source,
object destination,
Type sourceType,
Type destinationType,
Action<IMappingOperationOptions<object, object>> opts);
IQueryable<TDestination> ProjectTo<TDestination>(
IQueryable source,
object parameters = null,
params Expression<Func<TDestination, object>>[] membersToExpand);
IQueryable<TDestination> ProjectTo<TDestination>(
IQueryable source,
IDictionary<string, object> parameters,
params string[] membersToExpand);
IQueryable ProjectTo(
IQueryable source,
Type destinationType,
IDictionary<string, object> parameters = null,
params string[] membersToExpand);
}
实现类
namespace AutoMapper
{
public class Mapper : IMapper, IMapperBase, IInternalRuntimeMapper, IRuntimeMapper
{
private readonly IGlobalConfiguration _configuration;
private readonly Func<Type, object> _serviceCtor;
public Mapper(IConfigurationProvider configuration)
: this(configuration, configuration.Internal().ServiceCtor)
{
}
public Mapper(IConfigurationProvider configuration, Func<Type, object> serviceCtor)
{
this._configuration = (IGlobalConfiguration) configuration ??
throw new ArgumentNullException(nameof (configuration));
this._serviceCtor = serviceCtor ?? throw new NullReferenceException(nameof (serviceCtor));
this.DefaultContext = new ResolutionContext((IInternalRuntimeMapper) this);
}
internal ResolutionContext DefaultContext { get; }
ResolutionContext IInternalRuntimeMapper.DefaultContext => this.DefaultContext;
Func<Type, object> IInternalRuntimeMapper.ServiceCtor => this._serviceCtor;
public IConfigurationProvider ConfigurationProvider =>
(IConfigurationProvider) this._configuration;
public TDestination Map<TDestination>(object source) =>
this.Map<object, TDestination>(source, default (TDestination));
public TDestination Map<TDestination>(
object source,
Action<IMappingOperationOptions<object, TDestination>> opts)
{
return this.Map<object, TDestination>(source, default (TDestination), opts);
}
public TDestination Map<TSource, TDestination>(TSource source) =>
this.Map<TSource, TDestination>(source, default (TDestination));
public TDestination Map<TSource, TDestination>(
TSource source,
Action<IMappingOperationOptions<TSource, TDestination>> opts)
{
return this.Map<TSource, TDestination>(source, default (TDestination), opts);
}
public TDestination Map<TSource, TDestination>(TSource source,
TDestination destination) =>
this.MapCore<TSource, TDestination>(source, destination, this.DefaultContext);
public TDestination Map<TSource, TDestination>(
TSource source,
TDestination destination,
Action<IMappingOperationOptions<TSource, TDestination>> opts)
{
return this.MapWithOptions<TSource, TDestination>(source, destination, opts);
}
public object Map(object source, Type sourceType, Type destinationType) =>
this.Map(source, (object) null, sourceType, destinationType);
public object Map(
object source,
Type sourceType,
Type destinationType,
Action<IMappingOperationOptions<object, object>> opts)
{
return this.Map(source, (object) null, sourceType, destinationType, opts);
}
public object Map(object source, object destination, Type sourceType,
Type destinationType) => this.MapCore<object, object>(
source, destination, this.DefaultContext, sourceType, destinationType);
public object Map(
object source,
object destination,
Type sourceType,
Type destinationType,
Action<IMappingOperationOptions<object, object>> opts)
{
return this.MapWithOptions<object, object>(
source, destination, opts, sourceType, destinationType);
}
public IQueryable<TDestination> ProjectTo<TDestination>(
IQueryable source,
object parameters,
params Expression<Func<TDestination, object>>[] membersToExpand)
{
return source.ProjectTo<TDestination>(
this.ConfigurationProvider, parameters, membersToExpand);
}
public IQueryable<TDestination> ProjectTo<TDestination>(
IQueryable source,
IDictionary<string, object> parameters,
params string[] membersToExpand)
{
return source.ProjectTo<TDestination>(
this.ConfigurationProvider, parameters, membersToExpand);
}
public IQueryable ProjectTo(
IQueryable source,
Type destinationType,
IDictionary<string, object> parameters,
params string[] membersToExpand)
{
return source.ProjectTo(destinationType,
this.ConfigurationProvider, parameters, membersToExpand);
}
TDestination IInternalRuntimeMapper.Map<TSource, TDestination>(
TSource source,
TDestination destination,
ResolutionContext context,
Type sourceType,
Type destinationType,
MemberMap memberMap)
{
return this.MapCore<TSource, TDestination>(
source, destination, context, sourceType, destinationType, memberMap);
}
private TDestination MapWithOptions<TSource, TDestination>(
TSource source,
TDestination destination,
Action<IMappingOperationOptions<TSource, TDestination>> opts,
Type sourceType = null,
Type destinationType = null)
{
MappingOperationOptions<TSource, TDestination> options =
new MappingOperationOptions<TSource, TDestination>(this._serviceCtor);
opts((IMappingOperationOptions<TSource, TDestination>) options);
Action<TSource, TDestination> beforeMapAction = options.BeforeMapAction;
if (beforeMapAction != null)
beforeMapAction(source, destination);
destination = this.MapCore<TSource, TDestination>(
source, destination, new ResolutionContext((IInternalRuntimeMapper) this,
(IMappingOperationOptions) options), sourceType, destinationType);
Action<TSource, TDestination> afterMapAction = options.AfterMapAction;
if (afterMapAction != null)
afterMapAction(source, destination);
return destination;
}
private TDestination MapCore<TSource, TDestination>(
TSource source,
TDestination destination,
ResolutionContext context,
Type sourceType = null,
Type destinationType = null,
MemberMap memberMap = null)
{
TypePair RequestedTypes = new TypePair(typeof (TSource), typeof (TDestination));
TypePair RuntimeTypes;
ref TypePair local = ref RuntimeTypes;
Type SourceType = source?.GetType();
if ((object) SourceType == null)
SourceType = sourceType ?? typeof (TSource);
Type DestinationType = destination?.GetType();
if ((object) DestinationType == null)
DestinationType = destinationType ?? typeof (TDestination);
local = new TypePair(SourceType, DestinationType);
MapRequest mapRequest = new MapRequest(RequestedTypes, RuntimeTypes, memberMap);
return this._configuration.GetExecutionPlan<TSource, TDestination>(
in mapRequest)(source, destination, context);
}
}
}
abp mapper
abp mapper 映射接口定义最顶层的接口
public interface IObjectMapper
{
//提供映射的提供器,由它完成映射
IAutoObjectMappingProvider AutoObjectMappingProvider { get; }
TDestination Map<TSource, TDestination>(TSource source);
TDestination Map<TSource, TDestination>(TSource source, TDestination destination);
}
//此处的 TContext 指的是模块
public interface IObjectMapper<TContext> : IObjectMapper
{
}
IObjectMapper<in TSource, TDestination> abp 提供的映射方式 用户自己写映射,最简单的方法
public interface IObjectMapper<in TSource, TDestination>
{
TDestination Map(TSource source);
TDestination Map(TSource source, TDestination destination);
}
ABP 会自动发现注册 MyCustomUserMapper, 在你使用 IObjectMapper 将用户映射到 UserDto 时会自 动使用自定义映射. 一个类可以为不同的对象实现多个 IObjectMapper<TSource, TDestination>.
public class MyCustomUserMapper : IObjectMapper<User, UserDto>, ITransientDependency
{
public UserDto Map(User source)
{
//TODO: Create a new UserDto
}
public UserDto Map(User source, UserDto destination)
{
//TODO: Set properties of an existing UserDto
return destination;
}
}
如果上面的 IObjectMapper<TSource,TDestination> 麻烦可以使用如下的 abp 提供的更简单接口
原对象实现 IMapTo ,可以在对象上直接写映射关系,简单的映射可以这样做
public interface IMapTo<TDestination>
{
TDestination MapTo();
void MapTo(TDestination destination);
}
目标象实现 IMapFrom ,可以在对象上直接写映射关系,简单的映射可以这样做
public interface IMapFrom<in TSource>
{
void MapFrom(TSource source);
}
IAutoObjectMappingProvider
如果 abp 提供的 IObjectMapper<TSource,TDestination> 不能满足,需要引入外部的映射提供器
namespace Volo.Abp.ObjectMapping;
public interface IAutoObjectMappingProvider
{
TDestination Map<TSource, TDestination>(object source);
TDestination Map<TSource, TDestination>(TSource source, TDestination destination);
}
public interface IAutoObjectMappingProvider<TContext> : IAutoObjectMappingProvider
{
}
abp 默认是不支持 auto mapper 的 所以这里的实现是空实现,可以使用 abp 自己定义的接口做映射 ,只有引入 auto mapper 的情况才会提供 auto mapper 的实现 IAutoObjectMappingProvider
public sealed class NotImplementedAutoObjectMappingProvider
: IAutoObjectMappingProvider, ISingletonDependency
{
public TDestination Map<TSource, TDestination>(
object source)
{
throw new NotImplementedException($"Can not map from given object ({source})
to {typeof(TDestination).AssemblyQualifiedName}.");
}
public TDestination Map<TSource, TDestination>(TSource source, TDestination destination)
{
throw new NotImplementedException($"Can no map from {
typeof(TSource).AssemblyQualifiedName} to
{typeof(TDestination).AssemblyQualifiedName}.");
}
}
IObjectMapper 实现
namespace Volo.Abp.ObjectMapping;
public class DefaultObjectMapper : IObjectMapper, ITransientDependency
{
protected static ConcurrentDictionary<string, MethodInfo> MethodInfoCache { get; } =
new ConcurrentDictionary<string, MethodInfo>();
//外部的映射提供器
public IAutoObjectMappingProvider AutoObjectMappingProvider { get; }
protected IServiceProvider ServiceProvider { get; }
public DefaultObjectMapper(
IServiceProvider serviceProvider,
IAutoObjectMappingProvider autoObjectMappingProvider)
{
AutoObjectMappingProvider = autoObjectMappingProvider;
ServiceProvider = serviceProvider;
}
//没有提供默认的目标类的映射
public virtual TDestination Map<TSource, TDestination>(TSource source)
{
if (source == null)
{
return default!;
}
//IObjectMapper<TSource, TDestination> 这种处理
using (var scope = ServiceProvider.CreateScope())
{
//先看自己定义的映射,这种最简单的映射
var specificMapper = scope.ServiceProvider.
GetService<IObjectMapper<TSource, TDestination>>();
if (specificMapper != null)
{
return specificMapper.Map(source);
}
//先看自己定义的映射是集合类型的
var result = TryToMapCollection<TSource,
TDestination>(scope, source, default);
if (result != null)
{
return result;
}
}
//实现 MapTo<TDestination> 接口的源对象
if (source is IMapTo<TDestination> mapperSource)
{
return mapperSource.MapTo();
}
//实现 IMapFrom<TSource> 接口的目标对象
if (typeof(IMapFrom<TSource>).IsAssignableFrom(typeof(TDestination)))
{
try
{
//TODO: Check if TDestination has a proper constructor which takes TSource
//TODO: Check if TDestination has an empty constructor
///(in this case, use MapFrom)
//假设目标类型的构造器里有唯一参数的 source 的构造函数存在
return (TDestination)Activator.CreateInstance(typeof(TDestination), source)!;
}
catch
{
//TODO: Remove catch when TODOs are implemented above
}
}
//都不匹配使用外部侧提供器执行
return AutoMap<TSource, TDestination>(source);
}
//提供了默认的目标类的映射
public virtual TDestination Map<TSource, TDestination>(
TSource source, TDestination destination)
{
if (source == null)
{
return default!;
}
using (var scope = ServiceProvider.CreateScope())
{
//先看自己定义的映射,这种最简单的映射
var specificMapper = scope.ServiceProvider.GetService<
IObjectMapper<TSource, TDestination>>();
if (specificMapper != null)
{
return specificMapper.Map(source, destination);
}
//映射的是集合或素组类型 IObjectMapper<TSource, TDestination
var result = TryToMapCollection(scope, source, destination);
if (result != null)
{
return result;
}
}
//如果对象实现了 IMapTo<TDestination> 接口,直接映射在源对象上实现的用户映射代码
if (source is IMapTo<TDestination> mapperSource)
{
mapperSource.MapTo(destination);
return destination;
}
//目标类型实现了 IMapFrom<TSource> 接口直接映射
if (destination is IMapFrom<TSource> mapperDestination)
{
mapperDestination.MapFrom(source);
return destination;
}
//上面的都不能映射,最好用外部提供的映射器实现
return AutoMap(source, destination);
}
//IObjectMapper<,> 用户定义的集合或数组映射
protected virtual TDestination? TryToMapCollection<TSource, TDestination>(
IServiceScope serviceScope, TSource source, TDestination? destination)
{
//判断是否是映射集合
if (!IsCollectionGenericType<TSource, TDestination>(
out var sourceArgumentType, out var destinationArgumentType,
out var definitionGenericType))
{
return default;
}
//先处理是用户自己生成映射的
var mapperType = typeof(IObjectMapper<,>).MakeGenericType(
sourceArgumentType, destinationArgumentType);
var specificMapper = serviceScope.ServiceProvider.GetService(mapperType);
if (specificMapper == null)
{
//skip, no specific mapper
return default;
}
var cacheKey = $"{mapperType.FullName}_{(destination == null
? "MapMethodWithSingleParameter" : "MapMethodWithDoubleParameters")}";
//先存入缓存,这里的缓存没有存在的必要性
var method = MethodInfoCache.GetOrAdd(
cacheKey,
_ =>
{
return specificMapper
.GetType()
.GetMethods()
.First(x =>
//这里巧妙
x.Name == nameof(IObjectMapper<object, object>.Map) &&
//匹配方法参数个数
x.GetParameters().Length == (destination == null ? 1 : 2)
);
}
);
var sourceList = source!.As<IList>();
//生成一个空的集合和数组的目标对象
var result = definitionGenericType.IsGenericType
? Activator.CreateInstance(definitionGenericType.MakeGenericType(
destinationArgumentType))!.As<IList>()
: Array.CreateInstance(destinationArgumentType, sourceList.Count);
//目标类型默认不为空的,并且不是数组的,清空集合
if (destination != null && !destination.GetType().IsArray)
{
//Clear destination collection if destination not an array,
// We won't change array just same behavior as AutoMapper.
destination.As<IList>().Clear();
}
for (var i = 0; i < sourceList.Count; i++)
{
var invokeResult = destination == null
? method.Invoke(specificMapper, new [] { sourceList[i] })!
: method.Invoke(specificMapper, new [] { sourceList[i],
Activator.CreateInstance(destinationArgumentType)! })!;
if (definitionGenericType.IsGenericType)
{
//返回值集合添加,
result.Add(invokeResult);
//目标参数添加
destination?.As<IList>().Add(invokeResult);
}
else
{
result[i] = invokeResult;
}
}
if (destination != null && destination.GetType().IsArray)
{
//Return the new collection if destination is an array,
// We won't change array just same behavior as AutoMapper.
return (TDestination)result;
}
//Return the destination if destination exists.
// The parameter reference equals with return object.
return destination ?? (TDestination)result;
}
//映射双方是否是集合类型
protected virtual bool IsCollectionGenericType<TSource,
TDestination>(out Type sourceArgumentType,
out Type destinationArgumentType, out Type definitionGenericType)
{
sourceArgumentType = default!;
destinationArgumentType = default!;
definitionGenericType = default!;
//不是泛型不是集合类型
if ((!typeof(TSource).IsGenericType && !typeof(TSource).IsArray) ||
(!typeof(TDestination).IsGenericType && !typeof(TDestination).IsArray))
{
return false;
}
var supportedCollectionTypes = new[]
{
typeof(IEnumerable<>),
typeof(ICollection<>),
typeof(Collection<>),
typeof(IList<>),
typeof(List<>)
};
if (typeof(TSource).IsGenericType && supportedCollectionTypes.Any(
x => x == typeof(TSource).GetGenericTypeDefinition()))
{
sourceArgumentType = typeof(TSource).GenericTypeArguments[0];
}
if (typeof(TSource).IsArray)
{
sourceArgumentType = typeof(TSource).GetElementType()!;
}
if (sourceArgumentType == default!)
{
return false;
}
definitionGenericType = typeof(List<>);
if (typeof(TDestination).IsGenericType && supportedCollectionTypes.Any(
x => x == typeof(TDestination).GetGenericTypeDefinition()))
{
destinationArgumentType = typeof(TDestination).GenericTypeArguments[0];
if (typeof(TDestination).GetGenericTypeDefinition() == typeof(ICollection<>) ||
typeof(TDestination).GetGenericTypeDefinition() == typeof(Collection<>))
{
definitionGenericType = typeof(Collection<>);
}
}
if (typeof(TDestination).IsArray)
{
destinationArgumentType = typeof(TDestination).GetElementType()!;
definitionGenericType = typeof(Array);
}
return destinationArgumentType != default!;
}
//使用外部的映射器
protected virtual TDestination AutoMap<TSource, TDestination>(object source)
{
return AutoObjectMappingProvider.Map<TSource, TDestination>(source);
}
//使用外部的映射器
protected virtual TDestination AutoMap<TSource, TDestination>(
TSource source, TDestination destination)
{
return AutoObjectMappingProvider.Map<TSource, TDestination>(source, destination);
}
}
//此处的上下文是模块
public class DefaultObjectMapper<TContext> : DefaultObjectMapper, IObjectMapper<TContext>
{
public DefaultObjectMapper(
IServiceProvider serviceProvider,
IAutoObjectMappingProvider<TContext> autoObjectMappingProvider
) : base(
serviceProvider,
autoObjectMappingProvider)
{
}
}
AbpObjectMappingModule
public class AbpObjectMappingModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
//给 IObjectAccessor<ServiceExposingActionList> 里加入 action
//onServiceExposingContext 是在注入服务的时候,一个实现类及多个导出接口
context.Services.OnExposing(onServiceExposingContext =>
{
//Register types for IObjectMapper<TSource, TDestination> if implements
onServiceExposingContext.ExposedTypes.AddRange(
//onServiceExposingContext.ImplementationType,
//当前 ImplementationType 类型 是否满足 IObjectMapper<,> 接口约定
//当前 ImplementationType 类型的导出类型加入 ImplementationType 的接口类型
//只所以这样做是因为实现类如果有多个接口,默认注入的接口如果不是IObjectMapper<,>
//这里就需要人为的去干预把 IObjectMapper<,> 类型的接口作为实现类的导出类型
ReflectionHelper.GetImplementedGenericTypes(
onServiceExposingContext.ImplementationType,
typeof(IObjectMapper<,>)
)
);
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTransient(
typeof(IObjectMapper<>),
typeof(DefaultObjectMapper<>)
);
}
}
abp AutoMapper
AutoMapperAutoObjectMappingProvider 提供器
获取 auto mapper 提供的 IMapper
public interface IMapperAccessor
{
//获取 auto mapper 提供的 IMapper
IMapper Mapper { get; }
}
internal class MapperAccessor : IMapperAccessor
{
public IMapper Mapper { get; set; } = default!;
}
auto mapper IMapper 实现映射
public class AutoMapperAutoObjectMappingProvider : IAutoObjectMappingProvider
{
public IMapperAccessor MapperAccessor { get; }
public AutoMapperAutoObjectMappingProvider(IMapperAccessor mapperAccessor)
{
MapperAccessor = mapperAccessor;
}
public virtual TDestination Map<TSource, TDestination>(object source)
{
return MapperAccessor.Mapper.Map<TDestination>(source);
}
public virtual TDestination Map<TSource, TDestination>(
TSource source, TDestination destination)
{
return MapperAccessor.Mapper.Map(source, destination);
}
}
public class AutoMapperAutoObjectMappingProvider<TContext> :
AutoMapperAutoObjectMappingProvider, IAutoObjectMappingProvider<TContext>
{
public AutoMapperAutoObjectMappingProvider(IMapperAccessor mapperAccessor)
: base(mapperAccessor)
{
}
}
IAbpAutoMapperConfigurationContext 配置上下文
配置 auto mapper 的 profile 的上下文
namespace Volo. Abp. AutoMapper;
public interface IAbpAutoMapperConfigurationContext
{
//提供的 profile 文件,里面包含映射关系的表达式
IMapperConfigurationExpression MapperConfiguration { get; }
IServiceProvider ServiceProvider { get; }
}
public class AbpAutoMapperConfigurationContext : IAbpAutoMapperConfigurationContext
{
public IMapperConfigurationExpression MapperConfiguration { get; }
public IServiceProvider ServiceProvider { get; }
public AbpAutoMapperConfigurationContext(
IMapperConfigurationExpression mapperConfigurationExpression,
IServiceProvider serviceProvider)
{
MapperConfiguration = mapperConfigurationExpression;
ServiceProvider = serviceProvider;
}
}
AbpAutoMapperOptions
namespace Volo.Abp.AutoMapper;
public class AbpAutoMapperOptions
{
//配置上下文
public List<Action<IAbpAutoMapperConfigurationContext>> Configurators { get; }
public ITypeList<Profile> ValidatingProfiles { get; set; }
public AbpAutoMapperOptions()
{
Configurators = new List<Action<IAbpAutoMapperConfigurationContext>>();
ValidatingProfiles = new TypeList<Profile>();
}
public void AddMaps<TModule>(bool validate = false)
{
//模块所属程序集
var assembly = typeof(TModule).Assembly;
Configurators.Add(context =>
{
//把模块所在程序集内部的 profile 映射文件加入上下文的
//IMapperConfigurationExpression
context.MapperConfiguration.AddMaps(assembly);
});
//是否进行配置验证,有可能配置的字段无法匹配,提前进行验证
if (validate)
{
var profileTypes = assembly
.DefinedTypes
.Where(type => typeof(Profile).IsAssignableFrom(type)
&& !type.IsAbstract && !type.IsGenericType);
foreach (var profileType in profileTypes)
{
//需要验证的 profile 文件
ValidatingProfiles.Add(profileType);
}
}
}
public void AddProfile<TProfile>(bool validate = false)
where TProfile : Profile, new()
{
Configurators.Add(context =>
{
context.MapperConfiguration.AddProfile<TProfile>();
});
if (validate)
{
ValidateProfile(typeof(TProfile));
}
}
public void ValidateProfile<TProfile>(bool validate = true)
where TProfile : Profile
{
ValidateProfile(typeof(TProfile), validate);
}
public void ValidateProfile(Type profileType, bool validate = true)
{
if (validate)
{
ValidatingProfiles.AddIfNotContains(profileType);
}
else
{
ValidatingProfiles.Remove(profileType);
}
}
}
注册 profile 给 AbpAutoMapperOptions
[DependsOn(typeof(AbpAutoMapperModule))]
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
//注入 auto mapper 提供额提供器
context. Services. AddAutoMapperObjectMapper();
//这种方式是把 profile 全局加入 AbpAutoMapperOptions 配置项,所有模块共用 profile
Configure<AbpAutoMapperOptions>(options =>
{
//把模块内的profile 映射加入配置对象的上下文,
options. AddMaps<MyModule>();
//options. AddMaps<MyModule>(validate: true);
//也可以单独的添加 profile 文件
});
}
}
AbpAutoMapperModule
namespace Volo.Abp.AutoMapper;
[DependsOn(
typeof(AbpObjectMappingModule),
typeof(AbpObjectExtendingModule),
typeof(AbpAuditingModule)
)]
public class AbpAutoMapperModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddConventionalRegistrar(new AbpAutoMapperConventionalRegistrar());
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
//使用 auto mapper 作为提供器
context.Services.AddAutoMapperObjectMapper();
//通过工厂注入auto mapper 的 IConfigurationProvider 实现 mapperConfiguration
//auto mapper 内部需要使用 IConfigurationProvider
context.Services.AddSingleton<IConfigurationProvider>(sp =>
{
//局部 scope
using (var scope = sp.CreateScope())
{
//加载配置项目,里面有所有模块的profile 文件
var options = scope.ServiceProvider.GetRequiredService<
IOptions<AbpAutoMapperOptions>>().Value;
//加载通过 MapperConfiguration 配置的映射关系,参考 auto mapper 官方文档
//这个是在哪里注入的不明确
var mapperConfigurationExpression = sp.GetRequiredService<
IOptions<MapperConfigurationExpression>>().Value;
//用 mapperConfigurationExpression 生成一个上下文
var autoMapperConfigurationContext =
new AbpAutoMapperConfigurationContext(
mapperConfigurationExpression, scope.ServiceProvider);
// 把配置类的 profile 加入 autoMapperConfigurationContext
foreach (var configurator in options.Configurators)
{
//configurator 是个委托,这个委托负责把 profile 配置加入上下文
configurator(autoMapperConfigurationContext);
}
//生成 MapperConfiguration
var mapperConfiguration = new MapperConfiguration(
mapperConfigurationExpression);
foreach (var profileType in options.ValidatingProfiles)
{
//使用 mapperConfiguration 进行配置的验证,具体看 auto mapper 文档
mapperConfiguration.Internal().AssertConfigurationIsValid(
((Profile)Activator.CreateInstance(profileType)).ProfileName);
}
// 返回 auto mapper 的 mapperConfiguration
return mapperConfiguration;
}
});
//注入 auto mapper 的 IMapper
context.Services.AddTransient<IMapper>(sp => sp.GetRequiredService<
IConfigurationProvider>().CreateMapper(sp.GetService));
//注入 abp 包装的 MapperAccessor 对象
context.Services.AddTransient<MapperAccessor>(sp => new MapperAccessor()
{
Mapper = sp.GetRequiredService<IMapper>()
});
//注入 IMapperAccessor ,abp 归根结底是通过 通过 IMapperAccessor 拿到 最终的 IMapper
//IMapper 本质又是通过 IConfigurationProvider 生成的
//在 abp 内部使用的是 IMapperAccessor 进行的 映射
context.Services.AddTransient<IMapperAccessor>(
provider => provider.GetRequiredService<MapperAccessor>());
}
}
约定的注入 这些注入的接口是 auto mapper 定义的
public class AbpAutoMapperConventionalRegistrar : DefaultConventionalRegistrar
{
protected readonly Type[] OpenTypes = {
typeof(IValueResolver<,,>),
typeof(IMemberValueResolver<,,,>),
typeof(ITypeConverter<,>),
typeof(IValueConverter<,>),
typeof(IMappingAction<,>)
};
protected override bool IsConventionalRegistrationDisabled(Type type)
{
return !type. GetInterfaces(). Any(
x => x. IsGenericType && OpenTypes. Contains(x. GetGenericTypeDefinition())) ||
base. IsConventionalRegistrationDisabled(type);
}
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime. Transient;
}
}
注入 auto mapper 的 AutoMapperAutoObjectMappingProvider 映射提供器
public static class AbpAutoMapperServiceCollectionExtensions
{
public static IServiceCollection AddAutoMapperObjectMapper(
this IServiceCollection services)
{
//IAutoObjectMappingProvider 提供映射的提供器
//因为之前 abp mapper 模块已经注入过 nullObjectMappingProvider 提供器,
//所以这里使用服务替换
return services.Replace(
ServiceDescriptor.Transient<IAutoObjectMappingProvider,
AutoMapperAutoObjectMappingProvider>()
);
}
public static IServiceCollection AddAutoMapperObjectMapper<TContext>(
this IServiceCollection services)
{
return services.Replace(
ServiceDescriptor.Transient<IAutoObjectMappingProvider<TContext>,
AutoMapperAutoObjectMappingProvider<TContext>>()
);
}
}
按模块隔离 profile
[DependsOn(typeof(AbpAutoMapperModule))]
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
//注入 auto mapper 提供额提供器
context.Services.AddAutoMapperObjectMapper<MyModule>();
//这种方式是把 profile 全局加入 AbpAutoMapperOptions 配置项,所有模块共用 profile
Configure<AbpAutoMapperOptions>(options =>
{
//把模块内的profile 映射加入配置对象的上下文,
options. AddMaps<MyModule>();
//options. AddMaps<MyModule>(validate: true);
//也可以单独的添加 profile 文件
});
}
}
👍🎉🎊