查看不同的库甚至Microsoft代码,我注意到在代码中配置选项的两种不同方法:
ConfigureServices
可以在注册DependencyInjection
时完成:
services.AddMvc(options => { });
或Configure
app.UseStaticFiles(
new StaticFileOptions
{
ServeUnknownFileTypes = true
});
我试图找出哪种方式用于什么目的,但仍然不知道,假设创建自己的中间件并注册 DI 和用法。
您发现的有趣问题。
查看源代码,我发现了以下内容:
所有的中间件注册都是这个 UseMiddleware 函数的重载,它是IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
的重载。
在这些重载中,您可以为中间件硬指定自己的参数。假设构造函数中有几个字符串,DI 容器将无法解决此问题。
如果未设置参数,它会回退到IServiceProvider
以解析特定类型。 请参阅扩展类:Microsoft.Extensions.Internal.ActivatorUtilities
(内部:Microsoft.AspNetCore.Http.Abstractions.dll
)
技巧
至于最佳实践,请考虑以下几点(不过我的意见):
- 尽量避免在构造函数中使用简单类型,而使用 Options 类。
- 对于 IOptions 使用
services.Configure<>()
,因为您可以在此处从 ConfigSection => 应用程序设置中指定选项。 - 至于服务:请注意,中间件是一个单例! 因此,添加临时服务,对于此中间件,只会解析一次!
我认为最佳做法是: 在启动时将中间件及其依赖项注册为 IOC 中的单例。 然后自己解决并使用方法自行添加App.Use([yourDelegate])
.
此方法的优点是它比使用隐藏的 Microsoft 代码 + Microsoft最近发布了对 DI 容器的升级来检查注册范围是否正确匹配(如果不匹配,则警告您)更容易理解。
这个工具基本上是这样做的:它检查服务的依赖项是否具有较小的范围,然后服务本身:假设服务是范围:Singleton
并且依赖项是范围Transient
。 这意味着如果解析了Singleton
Transient
也会解析此单例,因此在下次使用此单例时不会再次解析。(所以这是一个隐藏的单例用法)。