有几种方法可以采用,但有些只是在类之间移动代码;我建议您考虑Assembly Scanning,因为我将其描述为下面的第二个选项:
1. “解决问题”:扩展方法
初始选项是使用extension methods 来配置服务。
这是一个将多个服务注册包装到一个扩展方法中的示例:
public static IServiceCollection AddCustomServices(this IServiceCollection services)
{
services.AddScoped<IBrowserConfigService, BrowserConfigService>();
services.AddScoped<IManifestService, ManifestService>();
services.AddScoped<IRobotsService, RobotsService>();
services.AddScoped<ISitemapService, SitemapService>();
services.AddScoped<ISitemapPingerService, SitemapPingerService>();
// Add your own custom services here e.g.
// Singleton - Only one instance is ever created and returned.
services.AddSingleton<IExampleService, ExampleService>();
// Scoped - A new instance is created and returned for each request/response cycle.
services.AddScoped<IExampleService, ExampleService>();
// Transient - A new instance is created and returned each time.
services.AddTransient<IExampleService, ExampleService>();
return services;
}
这可以在ConfigureServices内调用:
services.AddCustomServices();
注意:这对于特定配置(例如,当服务需要向其传递多个选项时)作为“构建器模式”很有用,但不能解决必须通过手动编码注册多个服务;本质上和写同样的代码,但是在不同的类文件中没有什么不同,而且还是需要人工维护。
2。 “解决问题”:装配体扫描
“最佳实践”选项是Assembly Scanning,用于根据Implemented Interfaces 自动查找和注册组件;下面是一个 Autofac 示例:
var assembly= Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
处理注册的生命周期(或范围)的一个技巧是使用标记接口(空接口),例如IScopedService,并使用它来扫描和注册具有适当生命周期的服务。这是注册多个服务的最低摩擦方法,它是自动的,因此是“零维护”。
注意:内置的 ASP.Net Core DI 实现不支持Assembly Scanning(作为 pf 当前,2016 版本);然而,Github(和 Nuget)上的 Scrutor 项目添加了这个功能,它将服务和类型注册压缩到:
var collection = new ServiceCollection();
collection.Scan(scan => scan
.FromAssemblyOf<ITransientService>()
.AddClasses(classes => classes.AssignableTo<ITransientService>())
.AsImplementedInterfaces()
.WithTransientLifetime()
.AddClasses(classes => classes.AssignableTo<IScopedService>())
.As<IScopedService>()
.WithScopedLifetime());
总结:
Assembly Scanning,结合Extension Methods(如果适用)将为您节省大量维护工作,并在应用程序启动时执行一次,随后进行缓存。它消除了手动代码服务注册的需要。