/// <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));
        }
Exemple #2
0
 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);
        }
Exemple #5
0
        /// <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);
        }
Exemple #6
0
        /// <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;
 }
Exemple #10
0
        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"));
        }
Exemple #11
0
        /// <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);
        }
Exemple #12
0
        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));
        }
Exemple #20
0
        /// <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);
        }
Exemple #21
0
 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));
     }
 }
Exemple #22
0
        /// <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);
        }
Exemple #23
0
        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);
        }
Exemple #25
0
 public DefaultAssemblerExecutor(IAssemblerProvider <T> assemblerProvider, IKernelServices kernelServices)
 {
     _assemblerProvider = assemblerProvider;
     _kernelServices    = kernelServices;
 }
Exemple #26
0
 public void Configure(IKernelServices kernelServices)
 {
     kernelServices.Services.Configure <TestOptions3>(r => { r.Name = "张三"; });
 }
Exemple #27
0
 public void Configure(IKernelServices kernelServices)
 {
     kernelServices.Services.AddDataProtection();
 }
 public void Configure(IKernelServices kernelService)
 {
     kernelService.AddNLogWithMysql(kernelService.RootConfiguration.GetSection("Logging:NLog"));
 }
Exemple #29
0
 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);
        }