使用Service Installer在.NET Core中配置依賴注入而無需任何代碼

目錄

介紹

描述


在本文中,我將解釋如何使用一個名爲IServiceInstaller的接口,您可以在配置依賴注入時使用它,然後使用簡單的反射代碼自動讀取它。

介紹

這是我們配置IServiceInstaller接口的方式:

public interface IServiceInstaller
{
   void InstallServices(IServiceCollection services, 
                        AppSettings appSettings, Assembly startupProjectAssembly);
}

描述

appSettings參數是一個類,其中包含所有appsettings.json文件配置值。您您確實可以使用IConfiguration並將對象傳遞給StartUp類。當您想在API層以外的另一層中實現這些文件時,使用startupProjectAssembly參數。

然後這就是我們使用反射來實現ConfigureServices方法的擴展方法的方式:

public static class ServiceInstallerExtensions
    {
        public static void InstallServicesInAssemblies
               (this IServiceCollection services, AppSettings appSettings)
        {
            var startupProjectAssembly = Assembly.GetCallingAssembly();
            var assemblies = new[] { startupProjectAssembly, Assembly.GetExecutingAssembly() };
            var installers = assemblies.SelectMany(a => a.GetExportedTypes())
                .Where(c => c.IsClass && !c.IsAbstract 
                && c.IsPublic && typeof(IServiceInstaller).IsAssignableFrom(c))
                .Select(Activator.CreateInstance).Cast<IServiceInstaller>().ToList();
            installers.ForEach(i => i.InstallServices
                              (services, appSettings, startupProjectAssembly));
        }
    }

最終,在添加所有服務之後,我們實現如下ConfigureServices方法:

public void ConfigureServices(IServiceCollection services)
        {
            //* HttpContextAccessor
            // services.AddHttpContextAccessor();
            //* Controllers
            services.AddControllers(options => { options.Filters.Add(new AuthorizeFilter()); })
                .AddNewtonsoftJson();

            //* Installers
            services.InstallServicesInAssemblies(_appSettings);
        }

完成了。現在,所有IServiceInstaller實現的服務將自動在ConfigureServices中註冊。

我們使用AutoRegisterDi包自動註冊DI服務。現在我們建立一個名爲:

 

public class RegisterServicesUsingAutoRegisterDiInstaller : IServiceInstaller
    {
        public void InstallServices
        (IServiceCollection services, AppSettings appSettings, Assembly startupProjectAssembly)
        {
            var dataAssembly = typeof(SomeRepository).Assembly;
            var serviceAssembly = typeof(SomeService).Assembly;
            var webFrameworkAssembly = Assembly.GetExecutingAssembly();
            var startupAssembly = startupProjectAssembly;
            var assembliesToScan = new[] 
            { dataAssembly, serviceAssembly, webFrameworkAssembly, startupAssembly };

            #region Generic Type Dependencies
            services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
            #endregion

            #region Scoped Dependency Interface
            services.RegisterAssemblyPublicNonGenericClasses(assembliesToScan)
                .Where(c => c.GetInterfaces().Contains(typeof(IScopedDependency)))
                .AsPublicImplementedInterfaces(ServiceLifetime.Scoped);
            #endregion

            #region Singleton Dependency Interface
            services.RegisterAssemblyPublicNonGenericClasses(assembliesToScan)
                .Where(c => c.GetInterfaces().Contains(typeof(ISingletonDependency)))
                .AsPublicImplementedInterfaces(ServiceLifetime.Singleton);
            #endregion

            #region Transient Dependency Interface
            services.RegisterAssemblyPublicNonGenericClasses(assembliesToScan)
                .Where(c => c.GetInterfaces().Contains(typeof(ITransientDependency)))
                .AsPublicImplementedInterfaces(); // Default is Transient
            #endregion

            #region Register DIs By Name
            services.RegisterAssemblyPublicNonGenericClasses(dataAssembly)
                .Where(c => c.Name.EndsWith("Repository")
                            && !c.GetInterfaces().Contains(typeof(ITransientDependency))
                            && !c.GetInterfaces().Contains(typeof(IScopedDependency))
                            && !c.GetInterfaces().Contains(typeof(ISingletonDependency)))
                .AsPublicImplementedInterfaces(ServiceLifetime.Scoped);

            services.RegisterAssemblyPublicNonGenericClasses(serviceAssembly)
                .Where(c => c.Name.EndsWith("Service")
                            && !c.GetInterfaces().Contains(typeof(ITransientDependency))
                            && !c.GetInterfaces().Contains(typeof(IScopedDependency))
                            && !c.GetInterfaces().Contains(typeof(ISingletonDependency)))
                .AsPublicImplementedInterfaces();
            #endregion
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章