/// <summary> /// 增加auto mapper自动化映射,注册了全局单例IMapper /// </summary> /// <param name="kernelService"></param> /// <returns></returns> public static IKernelServices AddAutoMapperByConvention(this IKernelServices kernelService) { var assemblies = ReflectionHelper.GetReferredAssemblies(typeof(AutoMapperExtensions).Assembly, DependencyContext.Default); return(kernelService.AddAutoMapperByConvention(assemblies)); }
public void Configure(IKernelServices kernelService) { if (!Options.Value.Enable) { return; } kernelService.AddAutoMapperByConvention(); }
/// <summary> /// 自动装配服务配置: <see cref="IServiceAssembler"/>, **服务装配类所有的条件特性都不可用** /// </summary> /// <param name="kernelServices"></param> /// <returns></returns> public static IKernelServices AssembleServices(this IKernelServices kernelServices) { using var serviceProvider = kernelServices.Services.BuildServiceProvider(); var autowireProvider = serviceProvider.GetRequiredService <IAssemblerExecutor <IServiceAssembler> >(); autowireProvider.Execute(serviceProvider, r => { r.Configure(kernelServices); }); return(kernelServices); }
/// <summary> /// 自动装载所有的配置options,<see cref="AutoOptionsAttribute"/> /// </summary> /// <param name="kernelServices"></param> /// <returns></returns> public static IKernelServices AssembleOptions(this IKernelServices kernelServices) { using var serviceProvider = kernelServices.Services.BuildServiceProvider(); var optionsAutowire = serviceProvider.GetRequiredService <IOptionsAssembler>(); optionsAutowire.ConfigureAll(kernelServices); return(kernelServices); }
/// <summary> /// 增加枚举服务,使用约定特性<see cref="JinkongEnumDefinitionAttribute"/>约定注册枚举数据 /// </summary> /// <param name="kernelBuilder"></param> /// <param name="configuration">可自定义的枚举描述节点配置,_Desc为枚举自身的描述(约定)</param> /// <param name="dependencyContext">依赖上下文,null使用默认上下文</param> /// <returns></returns> public static IKernelServices AddEnumsByConvention(this IKernelServices kernelBuilder, IConfiguration configuration = null, DependencyContext dependencyContext = null) { var enums = new Lazy <List <EnumModel> >(() => LoadEnumModels(configuration, dependencyContext)); kernelBuilder.Services.AddSingleton <IEnumService>(new DefaultEnumService(enums)); return(kernelBuilder); }
/// <summary> /// 增加nlog服务,需要在Program中调用UseNLog,使用mysql数据库 /// </summary> /// <param name="kernelServices"></param> /// <param name="nLogXmlConfigContent">nlog 配置文件内容,空则使用内置配置</param> /// <param name="loggingConfigs">日志推送配置</param> /// <returns></returns> public static IKernelServices AddNLogWithMysql( this IKernelServices kernelServices, IConfigurationSection loggingConfigs, string nLogXmlConfigContent = null) { var services = kernelServices.Services; services.Configure <NLogOptions>(loggingConfigs); var loggingOptions = loggingConfigs.Get <NLogOptions>(); #region 日志数据库 kernelServices.Services.AddDbContext <LogDbContext>(dbOptions => { dbOptions.UseMySql(loggingOptions.Conn, builder => { builder.MigrationsAssembly(typeof(LogDbContext).Assembly.GetName().FullName); }); }); #endregion #region nlog 配置文件自动处理 // 读取默认配置 if (nLogXmlConfigContent.IsNullOrWhiteSpace()) { using var stream = typeof(LogDbContext).Assembly.GetManifestResourceStream($"Jinkong.NLogger.Mysql.nlog.mysql.config"); using var sm = new StreamReader(stream !); nLogXmlConfigContent = sm.ReadToEnd(); } string filename = Path.Combine(Directory.GetCurrentDirectory(), "nlog.config"); StringBuilder ignores = new StringBuilder(); if (!loggingOptions.Ignores.IsNullOrEmpty()) { foreach (var item in loggingOptions.Ignores) { ignores.AppendLine($"\t\t\t\t<when condition=\"{item}\" action=\"Ignore\" />"); } } // 格式化配置文件 nLogXmlConfigContent = nLogXmlConfigContent.RazorFormat(new { loggingOptions.Email, loggingOptions.Conn, Ignores = ignores.ToString() }); File.WriteAllText(filename, nLogXmlConfigContent, Encoding.UTF8); NLogBuilder.ConfigureNLog(filename); #endregion return(kernelServices); }
public void Configure(IKernelServices kernelServices) { if (!Options.Value.Enable) { return; } kernelServices.Services.AddMemoryCache(); }
public IDictionary <Type, AssemblerDescriptor <T> > Load(IKernelServices kernelServices, IServiceProvider serviceProvider) { if (kernelServices == null) { throw new ArgumentNullException(nameof(kernelServices)); } if (serviceProvider == null) { throw new ArgumentNullException(nameof(serviceProvider)); } var type = typeof(T); var instances = serviceProvider.GetServices <T>(); var dic = new Dictionary <Type, AssemblerDescriptor <T> >(); foreach (var instance in instances) { var implementationType = instance.GetType(); var afterAtAttribute = implementationType.GetCustomAttribute <AfterAtAttribute>(false); var beforeAtAttribute = implementationType.GetCustomAttribute <BeforeAtAttribute>(false); var orderAttribute = implementationType.GetCustomAttribute <OrderAttribute>(false); var descriptor = new InnerAssemblerDescriptor <T>( implementationType, afterAtAttribute?.AfterAt, beforeAtAttribute?.BeforeAt, orderAttribute?.Order ?? 0, instance); dic.Add(implementationType, descriptor); } foreach (var item in dic) { if (item.Value.AfterAt is not null && item.Value.AfterAt.IsSubTypeOrEqualsOf(type) && dic.ContainsKey(item.Value.AfterAt)) { item.Value.Prevs.Add(item.Value.AfterAt); dic[item.Value.AfterAt].Nexts.Add(item.Key); } if (item.Value.BeforeAt is not null && item.Value.BeforeAt.IsSubTypeOrEqualsOf(type) && dic.ContainsKey(item.Value.BeforeAt)) { item.Value.Nexts.Add(item.Value.BeforeAt); dic[item.Value.BeforeAt].Prevs.Add(item.Key); } } return(dic); }
public ApplicationLifetimeHostedService( IAssemblerProvider <IApplicationStartAssembler> applicationStartAutowireProvider, IAssemblerProvider <IApplicationStopAssembler> applicationStopAutowireProvider, IKernelServices kernelServices, IServiceProvider serviceProvider) { ApplicationStartAutowireProvider = applicationStartAutowireProvider; ApplicationStopAutowireProvider = applicationStopAutowireProvider; KernelServices = kernelServices; ServiceProvider = serviceProvider; }
public void Configure(IKernelServices kernelService) { if (!Options.Value.Enable) { return; } var services = kernelService.Services; if (Options.Value.UseEmptyTemplateMsg) { services.AddSingleton <IWxTemplateMsg, EmptyWxTemplateMsg>(); } else { services.AddSingleton <IWxTemplateMsg, DefaultWxTemplateMsg>(); } services.AddSingleton <IWxAccessToken, DefaultWxAccessToken>(); services.AddSingleton <IWxMedia, DefaultWxMedia>(); services.AddSingleton <IWxPay, DefaultWxPay>(); var globalOptions = Options.Value.GlobalSettings; if (globalOptions == null) { throw new Exception("SdkOptions can't be null."); } if (!globalOptions.ThisHost.IsMatch(Consts.Regexs.Url)) { throw new Exception("SdkOptions.ThisHost must be url."); } if (!globalOptions.ProxyHost.IsNullOrWhiteSpace() && globalOptions.ProxyPort.HasValue) { if (globalOptions.ProxyUserName.IsNullOrWhiteSpace() || globalOptions.ProxyPassword.IsNullOrWhiteSpace()) { RequestUtility.SenparcHttpClientWebProxy = new WebProxy(globalOptions.ProxyHost, globalOptions.ProxyPort.Value); } else { NetworkCredential credential = new NetworkCredential(globalOptions.ProxyUserName, globalOptions.ProxyPassword); RequestUtility.SenparcHttpClientWebProxy = new WebProxy($"{globalOptions.ProxyHost}:{globalOptions.ProxyPort}", true, null, credential); } } services //Senparc.CO2NET 全局注册,主要是注册下面的节点Jinkong.Wx.SenparcSetting .AddSenparcWeixinServices(kernelService.RootConfiguration.GetSection("Jinkong.Wx")); }
/// <summary> /// 增加枚举服务,自定义导入枚举数据 /// </summary> /// <param name="kernelBuilder"></param> /// <param name="getOptionsFunc">可自定义的枚举描述</param> public static IKernelServices AddEnums(this IKernelServices kernelBuilder, Func <List <EnumModel> > getOptionsFunc) { if (getOptionsFunc == null) { throw new ArgumentNullException(nameof(getOptionsFunc)); } var enums = new Lazy <List <EnumModel> >(() => getOptionsFunc()); kernelBuilder.Services.AddSingleton <IEnumService>(new DefaultEnumService(enums)); return(kernelBuilder); }
public void Configure(IKernelServices kernelServices) { var dbContexts = ReflectionHelper.GetFinalSubTypes <DbContext>(); foreach (var dbContext in dbContexts) { if (GetEnableAutoMigration(dbContext, kernelServices.RootConfiguration)) { kernelServices.Services.AddAutoMigration(dbContext); } } }
/// <summary> /// 自定义装配<typeparamref name="T"/>类型 /// </summary> /// <param name="kernelServices"></param> /// <param name="autowireAction"></param> /// <returns></returns> public static IKernelServices Assemble <T>(this IKernelServices kernelServices, Action <T> autowireAction) where T : IAssembler { if (autowireAction is null) { throw new ArgumentNullException(nameof(autowireAction)); } using var serviceProvider = kernelServices.Services.BuildServiceProvider(); var autowireProvider = serviceProvider.GetRequiredService <IAssemblerExecutor <T> >(); autowireProvider.Execute(serviceProvider, autowireAction); return(kernelServices); }
public void ConfigureAll(IKernelServices kernelServices) { if (kernelServices is null) { throw new ArgumentNullException(nameof(kernelServices)); } var method = typeof(OptionsConfigurationServiceCollectionExtensions) .GetMethod("Configure", new[] { typeof(IServiceCollection), typeof(string), typeof(IConfiguration) }); if (method is null) { throw new MissingMethodException( "OptionsConfigurationServiceCollectionExtensions", "Configure<TOptions>(this IServiceCollection services, string name, IConfiguration config)"); } var services = kernelServices.Services; var dic = ReflectionHelper.GetTypesAndAttribute <AutoOptionsAttribute>(kernelServices.ScanFromDependencyContext); foreach (var(key, value) in dic) { var sectionName = value.Section; var section = kernelServices.RootConfiguration.GetSection(sectionName); method.MakeGenericMethod(key) .Invoke(null, new object[] { services, value.Name, section }); } using var serviceProvider = kernelServices.Services.BuildServiceProvider(); // options model validation foreach (var(key, value) in dic) { var optionsTypes = typeof(IOptions <>).MakeGenericType(key); (_, object?obj) = serviceProvider.GetRequiredService(optionsTypes).GetPropertyValue("Value") !; var res = ValidationHelper.Validate(obj, serviceProvider); if (res.Count > 0) { throw new KernelAssembleException( $"Invalid option, section: {value.Section}, option type: {key}, errors:{Environment.NewLine}{res.Select(r => r.ErrorMessage).Join(Environment.NewLine)}"); } } }
public void Configure(IKernelServices kernelService) { // 增加全局拦截器 kernelService.Services.ConfigureDynamicProxy(r => { r.Interceptors.AddTyped <TransactionalAttribute>( method => method.IsDefinedAttribute <TransactionalAttribute>(true) ); r.Interceptors.AddTyped <TransactionScopeAttribute>( method => method.IsDefinedAttribute <TransactionScopeAttribute>(true) ); }); }
/// <summary> /// 执行条件过滤 /// </summary> /// <param name="kernelServices"></param> /// <returns></returns> /// <exception cref="InvalidCastException"></exception> public static IServiceCollection DoFilter(this IKernelServices kernelServices) { using var serviceProvider = kernelServices.Services.BuildServiceProvider(); var filterProvider = serviceProvider.GetRequiredService <IFilterProvider>(); var hostEnvironment = serviceProvider.GetRequiredService <IHostEnvironment>(); // 按条件过滤服务注册 filterProvider.DoFilter( kernelServices.Services, kernelServices.RootConfiguration, hostEnvironment); return(kernelServices.Services); }
public void Configure(IKernelServices kernelService) { if (!Options.Enable) { return; } var csRedis = Options.CSRedisClientFactory?.Invoke() ?? new CSRedisClient(Options.ConnectionString, Options.Sentinels, Options.Readonly); RedisHelper.Initialization(csRedis); kernelService.Services.AddSingleton(csRedis); kernelService.Services.AddSingleton <IDistributedCache>( new Microsoft.Extensions.Caching.Redis.CSRedisCache(RedisHelper.Instance)); }
public void Configure(IKernelServices kernelService) { if (!Options.Value.Enable) { return; } kernelService.Services.AddHangfire(r => { r.SetDataCompatibilityLevel(CompatibilityLevel.Version_170) .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() .UseRedisStorage(RedisClient); }) .AddHangfireServer(); }
public void Configure(IKernelServices kernelServices) { kernelServices.Services.AddDbContext <TestDbContext1>(r => { var conn = kernelServices.RootConfiguration.GetValue <string>("ConnectionStrings:Conn1"); r.UseMySql(conn, ServerVersion.AutoDetect(conn), db => { db.MigrationsAssembly(typeof(EfCoreTestAutowire).Assembly.FullName); }); }) ; kernelServices.Services.AddDbContextPool <TestDbContext2>(r => { var conn = kernelServices.RootConfiguration.GetValue <string>("ConnectionStrings:Conn2"); r.UseMySql(conn, ServerVersion.AutoDetect(conn), db => { db.MigrationsAssembly(typeof(EfCoreTestAutowire).Assembly.FullName); }); }, 5) ; kernelServices.Services.AddDbContextPool <TestDbContext3>(r => { var conn = kernelServices.RootConfiguration.GetValue <string>("ConnectionStrings:Conn3"); r.UseMySql(conn, ServerVersion.AutoDetect(conn), db => { db.MigrationsAssembly(typeof(EfCoreTestAutowire).Assembly.FullName); }); }, 5) ; kernelServices.Services.AddDbContextPool <TestDbContext4>(r => { var conn = kernelServices.RootConfiguration.GetValue <string>("ConnectionStrings:Conn4"); r.UseMySql(conn, ServerVersion.AutoDetect(conn), db => { db.MigrationsAssembly(typeof(EfCoreTestAutowire).Assembly.FullName); }); }, 5) ; kernelServices.Services.AddDbContextPool <TestDbContext5>(r => { var conn = kernelServices.RootConfiguration.GetValue <string>("ConnectionStrings:Conn5"); r.UseMySql(conn, ServerVersion.AutoDetect(conn), db => { db.MigrationsAssembly(typeof(EfCoreTestAutowire).Assembly.FullName); }); }, 5) ; kernelServices.Services.AddDbContextPool <TestDbContext6>(r => { var conn = kernelServices.RootConfiguration.GetValue <string>("ConnectionStrings:Conn6"); r.UseMySql(conn, ServerVersion.AutoDetect(conn), db => { db.MigrationsAssembly(typeof(EfCoreTestAutowire).Assembly.FullName); }); }, 5) ; kernelServices.Services.AddAutoMigration <TestDbContext4>(); kernelServices.Services.AddAutoMigration(typeof(TestDbContext5)); }
/// <summary> /// /// </summary> /// <param name="kernelBuilder"></param> /// <param name="configuration"></param> /// <returns></returns> public static IKernelServices AddBank(this IKernelServices kernelBuilder, IConfigurationSection configuration = null) { var services = kernelBuilder.Services; if (configuration != null) { services.Configure <BankOptions>(configuration); } else { services.Configure <BankOptions>(r => { var configurationOption = configuration?.Get <BankOptions>(); r.Datas = new List <BankModel>(); using (var stream = typeof(IBankService).Assembly.GetManifestResourceStream("Jinkong.Bank.data.txt")) { var lines = stream.ReadToString().Split(new[] { '\n' }); foreach (var item in lines) { if (item.IsNullOrWhiteSpace()) { continue; } var line = item.Trim().Trim('\r'); var arr = line.Split(new[] { ' ', '\t' }, System.StringSplitOptions.RemoveEmptyEntries); if (arr.Length >= 2) { r.Datas.Add(new BankModel { Code = arr[0].Trim(), Name = arr[1].Trim(), Logo = $"https://apimg.alipay.com/combo.png?d=cashier&t={arr[0]}" }); } } } }); } return(kernelBuilder); }
public void Configure(IKernelServices kernelService) { if (!Options.Enable) { return; } if (Options.Buckets.HasRepeat(r => r.Bucket)) { throw new InvalidOperationException($"重复的bucket配置"); } if (Options.Buckets.Count(r => r.IsDefault) > 1) { throw new InvalidOperationException($"默认bucket只能配置一个"); } foreach (var item in Options.Buckets.OrderBy(r => r.IsDefault)) { kernelService.Services.AddSingleton <IAliyunOssProvider>(new AliyunOssDefaultProvider(item)); } }
/// <summary> /// 增加地理编码接口 /// </summary> /// <param name="kernelBuilder"></param> /// <param name="configuration">GeocoderOptions配置节点,null则使用默认参数,里面的key和areas也一样优先使用传入的配置,否则使用默认配置</param> /// <returns></returns> public static IKernelServices AddGeoCoder(this IKernelServices kernelBuilder, IConfiguration configuration = null) { var services = kernelBuilder.Services; if (configuration != null) { services.Configure <GeoCoderOptions>(configuration); } else { services.Configure <GeoCoderOptions>(r => { var configurationOption = configuration?.Get <GeoCoderOptions>(); using (var stream = typeof(IAreaService).Assembly.GetManifestResourceStream("Jinkong.GeoCoder.data.json")) { var str = stream.ReadToString(); var options = JsonConvert.DeserializeObject <GeoCoderOptions>(str); if (configurationOption != null && !configurationOption.Key.IsNullOrWhiteSpace()) { r.Key = configurationOption.Key; } else { r.Key = options.Key; } if (configurationOption != null && !configurationOption.Areas.IsNullOrEmpty()) { r.Areas = configurationOption.Areas; } else { r.Areas = options.Areas; } } }); } return(kernelBuilder); }
public void Configure(IKernelServices kernelServices) { var services = kernelServices.Services; using var serviceProvider = services.BuildServiceProvider(); var mchs = serviceProvider.GetService <IOptions <PayMchOptions> >(); foreach (var item in mchs.Value.Mchs) { var wxMch = item.Value.FirstOrDefault(r => r.PayType == PayType.WxPay); if (wxMch == null) { continue; } // 需要先注册带证书的httpclient var key = TenPayHelper.GetRegisterKey(wxMch.MchId, null); services.AddCertHttpClient(key, wxMch.WxCertPwd, wxMch.WxCertPath); } }
/// <summary> /// 注册约定的服务: Scoped/Singleton/Transient /// </summary> /// <param name="kernelServices"></param> /// <returns></returns> public static IKernelServices RegistryConventionServices(this IKernelServices kernelServices) { using var serviceProvider = kernelServices.Services.BuildServiceProvider(); var serviceDescriptorProvider = serviceProvider.GetRequiredService <IServiceDescriptorProvider>(); var types = ReflectionHelper.GetTypesAndAttribute <ServiceAttribute>(kernelServices.ScanFromDependencyContext, false); foreach (var item in types) { var services = serviceDescriptorProvider.GetDescriptor(item.Key); foreach (var shashlikServiceDescriptor in services) { if (!kernelServices.Services.AnyService(shashlikServiceDescriptor.ServiceType, shashlikServiceDescriptor.ImplementationType !)) { kernelServices.Services.Add(shashlikServiceDescriptor); } } } return(kernelServices); }
public DefaultAssemblerExecutor(IAssemblerProvider <T> assemblerProvider, IKernelServices kernelServices) { _assemblerProvider = assemblerProvider; _kernelServices = kernelServices; }
public void Configure(IKernelServices kernelServices) { kernelServices.Services.Configure <TestOptions3>(r => { r.Name = "张三"; }); }
public void Configure(IKernelServices kernelServices) { kernelServices.Services.AddDataProtection(); }
public void Configure(IKernelServices kernelService) { kernelService.AddNLogWithMysql(kernelService.RootConfiguration.GetSection("Logging:NLog")); }
public void Configure(IKernelServices kernelService) { kernelService.AddBank(); }
/// <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); }