使用 Simple Injector 的 asp.net Core Web API 服务的正确 DefaultScopedLifestyle 是什么?
What is the correct DefaultScopedLifestyle for an asp.net Core Web API service using Simple Injector?
我正在尝试使用 Simple Injector 创建 .net 核心 WebApi 服务。在我的 Startup.cs 我有这个:
public Startup(IHostingEnvironment env)
{
// Setup configuration stuff
container = new Container();
container.Options.DefaultScopedLifestyle = new AspNetRequestLifestyle(); // This is as specified in the docs.
}
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddOptions();
services.AddSingleton<IControllerActivator>(
new SimpleInjectorControllerActivator(this.container));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSimpleInjectorAspNetRequestScoping(this.container);
InitializeContainer(app); // This registers stuff
this.container.Verify(); // This blows up.
app.UseMvc();
}
private void InitializeContainer(IApplicationBuilder app)
{
// Add application presentation components:
this.container.RegisterMvcControllers(app);
this.container.RegisterSingleton(new Log4NetAdapter(LogManager.GetLogger("Services.Api").Logger));
// Register other stuff here.
}
这编译得很好。但是当我尝试启动该服务时,我在 container.Verify()
步骤中收到以下错误消息:
{"The configuration is invalid. The following diagnostic warnings were reported:
-[Disposable Transient Component] MessageController is registered as transient, but implements IDisposable.
See the Error property for detailed information about the warnings. Please see https://simpleinjector.org/diagnostics how to fix problems and how to suppress individual warnings."}
-[Disposable Transient Component] MessageController is registered as transient, but implements IDisposable.
The configuration is invalid. The following diagnostic warnings were reported:
See the Error property for detailed information about the warnings. Please see https://simpleinjector.org/diagnostics how to fix problems and how to suppress individual warnings.
我尝试包括必要的 nuget 包以使用 WebApiRequestLifestyle
,但它
似乎只对标准.Net 项目有效;不是 .net 核心。
我在文档中找到了 this page。我可以通过忽略针对我的特定控制器的警告来 运行 服务:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSimpleInjectorAspNetRequestScoping(this.container);
InitializeContainer(app); // This registers stuff
var registration = container.GetRegistration(typeof(MessageController)).Registration;
registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent, "This is a Web API controller. Disposal should be handled by the system.");
this.container.Verify(); // Now this works
app.UseMvc();
}
问题是现在我必须进入并抑制每个额外控制器的警告。这不应该由默认生活方式处理吗?
谈到 ASP.NET 核心,只有一种范围内的生活方式:AspNetRequestLifestyle
。无论您是构建 Core MVC 还是 Core Web API 应用程序,这种生活方式都适用。
您遇到的错误与所选范围内的生活方式无关。如果您没有配置 scoped 生活方式,您将获得完全相同的生活方式。
如果您关注 the integration guide,您将看到以下代码行:
container.RegisterMvcControllers(app);
RegisterMvcControllers
将为您注册所有控制器(这是 adviced practice) and while doing so, apply this suppression per controller for you. Suppressing the warning is essential, because there is a design flaw in MVC concerning controllers. The controller base class implements IDisposable
which causes each derived controller to implement it as well. This is a Dependency Inversion Principle 违规行为。
因为控制器实现了 IDisposable
,Simple Injector 对此发出警告,因为它看到一个需要处理的瞬态组件,因为 Simple Injector 不会为您处理瞬态(因为并不总是有可用的范围可以存储瞬变以供以后处理的地方)。
一个典型的解决方案是将这样的一次性组件注册为 Scoped
,但在控制器的情况下,这也会导致复杂性,因为这意味着每个依赖项都必须(至少)有范围。
那么RegisterMvcControllers
在幕后所做的就是分析派生的class是否覆盖了Dispose(bool)
。如果它不覆盖 Dispose(bool)
,警告将被抑制。如果它不覆盖 Dispose
,则警告可以被抑制,因为基础 class 不处理任何东西(这就是为什么基础 class 不应该实现 IDisposable
首先)。这意味着一旦您在控制器中覆盖 Dispose(bool)
,您将(正确地)再次看到此警告弹出窗口。
我最好的猜测是 MessageController
覆盖 Dispose(bool)
或 MessageController
派生自覆盖 Dispose(bool)
.[=29= 的自定义基础 class ]
请注意,您的控制器几乎不应该有处理逻辑:
- 控制器应该只处理表示逻辑,这意味着任何其他逻辑都应该提取到您注入控制器的另一个 class 中。
- 应用程序组件(例如控制器)不应处理其传入的任何依赖项;这是您的 DI 容器应该为您处理的事情。
在极少数情况下,控制器实际上应该自行处理,您可以覆盖该特定控制器的默认注册并将其注册为作用域。这将确保控制器在请求结束时得到处理。
因此 RegisterMvcControllers
方法围绕 ASP.NET Core MVC 中的这个设计怪癖为您实现了这个丑陋的技巧。
我正在尝试使用 Simple Injector 创建 .net 核心 WebApi 服务。在我的 Startup.cs 我有这个:
public Startup(IHostingEnvironment env)
{
// Setup configuration stuff
container = new Container();
container.Options.DefaultScopedLifestyle = new AspNetRequestLifestyle(); // This is as specified in the docs.
}
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddOptions();
services.AddSingleton<IControllerActivator>(
new SimpleInjectorControllerActivator(this.container));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSimpleInjectorAspNetRequestScoping(this.container);
InitializeContainer(app); // This registers stuff
this.container.Verify(); // This blows up.
app.UseMvc();
}
private void InitializeContainer(IApplicationBuilder app)
{
// Add application presentation components:
this.container.RegisterMvcControllers(app);
this.container.RegisterSingleton(new Log4NetAdapter(LogManager.GetLogger("Services.Api").Logger));
// Register other stuff here.
}
这编译得很好。但是当我尝试启动该服务时,我在 container.Verify()
步骤中收到以下错误消息:
{"The configuration is invalid. The following diagnostic warnings were reported: -[Disposable Transient Component] MessageController is registered as transient, but implements IDisposable. See the Error property for detailed information about the warnings. Please see https://simpleinjector.org/diagnostics how to fix problems and how to suppress individual warnings."}
-[Disposable Transient Component] MessageController is registered as transient, but implements IDisposable. The configuration is invalid. The following diagnostic warnings were reported: See the Error property for detailed information about the warnings. Please see https://simpleinjector.org/diagnostics how to fix problems and how to suppress individual warnings.
我尝试包括必要的 nuget 包以使用 WebApiRequestLifestyle
,但它
似乎只对标准.Net 项目有效;不是 .net 核心。
我在文档中找到了 this page。我可以通过忽略针对我的特定控制器的警告来 运行 服务:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSimpleInjectorAspNetRequestScoping(this.container);
InitializeContainer(app); // This registers stuff
var registration = container.GetRegistration(typeof(MessageController)).Registration;
registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent, "This is a Web API controller. Disposal should be handled by the system.");
this.container.Verify(); // Now this works
app.UseMvc();
}
问题是现在我必须进入并抑制每个额外控制器的警告。这不应该由默认生活方式处理吗?
谈到 ASP.NET 核心,只有一种范围内的生活方式:AspNetRequestLifestyle
。无论您是构建 Core MVC 还是 Core Web API 应用程序,这种生活方式都适用。
您遇到的错误与所选范围内的生活方式无关。如果您没有配置 scoped 生活方式,您将获得完全相同的生活方式。
如果您关注 the integration guide,您将看到以下代码行:
container.RegisterMvcControllers(app);
RegisterMvcControllers
将为您注册所有控制器(这是 adviced practice) and while doing so, apply this suppression per controller for you. Suppressing the warning is essential, because there is a design flaw in MVC concerning controllers. The controller base class implements IDisposable
which causes each derived controller to implement it as well. This is a Dependency Inversion Principle 违规行为。
因为控制器实现了 IDisposable
,Simple Injector 对此发出警告,因为它看到一个需要处理的瞬态组件,因为 Simple Injector 不会为您处理瞬态(因为并不总是有可用的范围可以存储瞬变以供以后处理的地方)。
一个典型的解决方案是将这样的一次性组件注册为 Scoped
,但在控制器的情况下,这也会导致复杂性,因为这意味着每个依赖项都必须(至少)有范围。
那么RegisterMvcControllers
在幕后所做的就是分析派生的class是否覆盖了Dispose(bool)
。如果它不覆盖 Dispose(bool)
,警告将被抑制。如果它不覆盖 Dispose
,则警告可以被抑制,因为基础 class 不处理任何东西(这就是为什么基础 class 不应该实现 IDisposable
首先)。这意味着一旦您在控制器中覆盖 Dispose(bool)
,您将(正确地)再次看到此警告弹出窗口。
我最好的猜测是 MessageController
覆盖 Dispose(bool)
或 MessageController
派生自覆盖 Dispose(bool)
.[=29= 的自定义基础 class ]
请注意,您的控制器几乎不应该有处理逻辑:
- 控制器应该只处理表示逻辑,这意味着任何其他逻辑都应该提取到您注入控制器的另一个 class 中。
- 应用程序组件(例如控制器)不应处理其传入的任何依赖项;这是您的 DI 容器应该为您处理的事情。
在极少数情况下,控制器实际上应该自行处理,您可以覆盖该特定控制器的默认注册并将其注册为作用域。这将确保控制器在请求结束时得到处理。
因此 RegisterMvcControllers
方法围绕 ASP.NET Core MVC 中的这个设计怪癖为您实现了这个丑陋的技巧。