目錄
在本文中,我將解釋如何使用一個名爲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
}
}