public AutoMapperAdapter(IConfigurationProvider configurationProvider) { _mapper = new global::AutoMapper.Mapper(configurationProvider); }
/// <summary> /// 增加auto mapper自动化映射,注册了全局单例IMapper /// </summary> /// <param name="kernelService"></param> /// <param name="assemblies">需要注册的程序集</param> /// <returns></returns> public static IKernelServices AddAutoMapperByConvention(this IKernelServices kernelService, IEnumerable <Assembly> assemblies) { if (assemblies is null) { throw new ArgumentNullException(nameof(assemblies)); } var configuration = new MapperConfiguration(config => { var method = config.GetType().GetTypeInfo().GetMethod("CreateMap", new Type[] { typeof(MemberList) }); if (method is null || !method.IsGenericMethodDefinition) { throw new MissingMethodException(nameof(IMapperConfigurationExpression), "CreateMap"); } //.Single(r => r.Name == "CreateMap" && r.IsGenericMethodDefinition && r.GetParameters().Length == 1); foreach (var assembly in assemblies) { var iMapFrom1Types = assembly.DefinedTypes.Where(r => !r.IsAbstract && r.IsClass && r.IsSubTypeOfGenericType(typeof(IMapFrom <>))).ToList(); var iMapFromTypes = assembly.DefinedTypes.Where(r => !r.IsAbstract && r.IsClass && r.IsSubTypeOfGenericType(typeof(IMapFrom <,>))).ToList(); var iMapTo1Types = assembly.DefinedTypes .Where(r => !r.IsAbstract && r.IsClass && r.IsSubTypeOfGenericType(typeof(IMapTo <>))).ToList(); var iMapToTypes = assembly.DefinedTypes.Where(r => !r.IsAbstract && r.IsClass && r.IsSubTypeOfGenericType(typeof(IMapTo <,>))).ToList(); // IMapFrom<TFrom> foreach (var item in iMapFrom1Types) { var interfaces = item.GetAllInterfaces(false); var fromTypes = interfaces .Where(r => r.IsGenericType && r.GenericTypeArguments.Length == 1 && r.FullName !.StartsWith(typeof(IMapFrom <>).FullName !)) .Select(r => r.GenericTypeArguments[0]) .ToList(); foreach (var fromType in fromTypes) { config.CreateMap(fromType, item, MemberList.None); } } // IMapFrom<TFrom, TDest> foreach (var item in iMapFromTypes) { var interfaces = item.GetAllInterfaces(false); var interfaceTypes = interfaces.Where(r => r.IsGenericType && r.GenericTypeArguments.Length == 2 && r.FullName !.StartsWith(typeof(IMapFrom <,>).FullName !)).ToHashSet(); if (interfaceTypes.IsNullOrEmpty()) { continue; } foreach (var interfaceType in interfaceTypes) { var fromType = interfaceType.GenericTypeArguments[0]; var destType = interfaceType.GenericTypeArguments[1]; var expression = method.MakeGenericMethod(fromType, destType) .Invoke(config, new object[] { MemberList.None }); if (expression is null) { throw new InvalidConstraintException($"[AutoMapper] `CreateMap` method return null"); } var expressionType = typeof(IMappingExpression <,>).MakeGenericType(fromType, destType); var configMethod = item.GetMethods().First(r => r.Name == "Config" && r.GetParameters().Length == 1 && r.GetParameters().First().ParameterType == expressionType); object?obj; try { obj = Activator.CreateInstance(item); } catch { throw new InvalidConstraintException( $"[AutoMapper] can not create instance of {item}, must contains non-argument constructor"); } if (obj is null) { throw new InvalidConstraintException( $"[AutoMapper] can not create instance of {item}, must contains non-argument constructor"); } try { configMethod.Invoke(obj, new object[] { expression }); using (obj as IDisposable) { } } catch (Exception e) { throw new InvalidConstraintException( $"[AutoMapper] create mapper {fromType}->{destType} error on type {item}.", e); } } } // IMapTo < TDest > foreach (var item in iMapTo1Types) { var interfaces = item.GetAllInterfaces(false); var toTypes = interfaces .Where(r => r.IsGenericType && r.GenericTypeArguments.Length == 1 && r.FullName !.StartsWith(typeof(IMapTo <>).FullName !)) .Select(r => r.GenericTypeArguments[0]) .ToList(); if (toTypes.IsNullOrEmpty()) { continue; } foreach (var toType in toTypes) { config.CreateMap(item, toType, MemberList.None); } } // IMapTo<TDest, TSource> foreach (var item in iMapToTypes) { var interfaces = item.GetAllInterfaces(false); var interfaceTypes = interfaces.Where(r => r.IsGenericType && r.GenericTypeArguments.Length == 2 && r.FullName !.StartsWith(typeof(IMapTo <,>).FullName !)).ToList(); if (interfaceTypes.IsNullOrEmpty()) { continue; } foreach (var interfaceType in interfaceTypes) { var destType = interfaceType.GenericTypeArguments[0]; var fromType = interfaceType.GenericTypeArguments[1]; var expression = method.MakeGenericMethod(fromType, destType) .Invoke(config, new object[] { MemberList.None }); if (expression is null) { throw new InvalidConstraintException($"[AutoMapper] `CreateMap` method return null"); } var expressionType = typeof(IMappingExpression <,>).MakeGenericType(fromType, destType); var configMethod = item.GetMethods().First(r => r.Name == "Config" && r.GetParameters().Length == 1 && r.GetParameters().First().ParameterType == expressionType); object?obj; try { obj = Activator.CreateInstance(item); } catch { throw new InvalidConstraintException( $"[AutoMapper] can not create instance of {item}, must contains non-argument constructor"); } if (obj is null) { throw new InvalidConstraintException( $"[AutoMapper] can not create instance of {item}, must contains non-argument constructor"); } try { configMethod.Invoke(obj, new object[] { expression }); using (obj as IDisposable) { } } catch (Exception e) { throw new InvalidConstraintException( $"[AutoMapper] create mapper {fromType}->{destType} error on type {item}.", e); } } } } }); configuration.AssertConfigurationIsValid(); var mapper = new global::AutoMapper.Mapper(configuration); ShashlikAutoMapper.Instance = mapper; kernelService.Services.AddSingleton <IMapper>(mapper); return(kernelService); }