目录
在本文中,我将解释如何使用一个名为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
}
}