配置中间件选项

Configuring options for middleware

查看不同的库甚至 Microsoft 代码,我注意到在代码中配置选项的两种不同方式:

ConfigureServices注册的时候就可以做到DependencyInjection:

services.AddMvc(options => { });

Configure

app.UseStaticFiles(
     new StaticFileOptions
     {
        ServeUnknownFileTypes = true
     });

我试图找出哪种方式用于哪种目的但仍然不知道,假设创建自己的中间件并注册 DI 和用法。

您发现了一个有趣的问题。

查看源代码我发现了以下内容:

所有的中间件注册都是这个UseMiddleware函数的重载,是IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);.

的重载

在这些重载中,您可以为中间件硬指定您自己的参数。假设你在构造函数中有几个字符串,DI 容器将无法解决这个问题。

如果未设置参数,它会回退到 IServiceProvider 来解析特定类型。查看扩展名 class:Microsoft.Extensions.Internal.ActivatorUtilities(内部:Microsoft.AspNetCore.Http.Abstractions.dll

提示

至于最佳实践,请考虑以下内容(尽管是我的意见):

  • 尽量避免在构造函数中使用简单类型,而是使用选项 class。
  • 对于 IOptions,请使用 services.Configure<>(),因为您可以在此处指定来自 ConfigSection => appsettings 的选项。
  • 至于服务:请注意中间件是单例!所以添加一个临时服务,只会为这个中间件解析一次!

我认为最佳做法是:在启动时在 IOC 中将中间件及其依赖项注册为单例。然后自己解决,用方法App.Use([yourDelegate]).

自己添加

这种方法的优点是它比使用隐藏的微软代码更容易理解+微软最近发布了对 DI 容器的升级来检查你的注册范围是否正确匹配(如果不匹配则警告你)。

这个工具基本上是这样做的:它检查服务的依赖项是否具有比服务本身更小的范围:假设服务是范围:Singleton 并且依赖项是范围Transient。这意味着如果 Singleton 被解析,Transient 也被解析为这个单例,因此在下次使用这个单例时不会再次解析。 (所以它是一个隐藏的单例用法)。