【问题标题】:What is the correct DefaultScopedLifestyle for an asp.net Core Web API service using Simple Injector?使用 Simple Injector 的 asp.net Core Web API 服务的正确 DefaultScopedLifestyle 是什么?
【发布时间】:2017-05-12 04:21:48
【问题描述】:

我正在尝试使用 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() 步骤中收到以下错误消息:

{"配置无效。报告了以下诊断警告: -[Disposable Transient Component] MessageController 注册为瞬态,但实现了 IDisposable。 有关警告的详细信息,请参阅错误属性。请参阅https://simpleinjector.org/diagnostics 如何解决问题以及如何抑制个别警告。"}

-[Disposable Transient Component] MessageController 注册为transient,但实现了IDisposable。 配置无效。报告了以下诊断警告: 有关警告的详细信息,请参阅错误属性。请参阅https://simpleinjector.org/diagnostics 如何解决问题以及如何抑制个别警告。

我尝试包含必要的 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();
}

问题在于,现在我必须进入并禁止对每个额外的控制器发出警告。这不应该由默认生活方式来处理吗?

【问题讨论】:

  • 您使用的是哪个版本的 SI 和集成包?

标签: .net simple-injector asp.net-core-webapi


【解决方案1】:

对于 ASP.NET Core,只有一种范围生活方式:AspNetRequestLifestyle。无论您是构建 Core MVC 还是 Core Web API 应用程序,这种生活方式都适用。

您遇到的错误与所选范围内的生活方式无关。如果您没有配置范围生活方式,您将获得完全相同的生活方式。

如果您关注the integration guide,您将看到以下代码行:

container.RegisterMvcControllers(app);

RegisterMvcControllers 将为您注册所有控制器(即adviced practice),同时为您应用此抑制每个控制器。抑制警告是必不可少的,因为在 MVC 中有一个 design flaw 与控制器有关。控制器基类实现IDisposable,这导致每个派生控制器也实现它。这是Dependency Inversion Principle 违规。

因为控制器实现了IDisposable,Simple Injector 对此发出警告,因为它看到了一个需要处理的瞬态组件,因为 Simple Injector 不会为您处理瞬态(因为并不总是有一个可用的范围让瞬态可以储存起来以备后用)。

一个典型的解决方案是将这样的一次性组件注册为Scoped,但在控制器的情况下,这也会导致复杂性,因为这意味着每个依赖项都必须(至少)有范围。

那么RegisterMvcControllers在幕后所做的就是分析派生类是否覆盖Dispose(bool)。如果它不覆盖Dispose(bool),则警告将被禁止。如果它不覆盖Dispose,则可以抑制警告,因为基类不处理任何东西(这就是为什么基类首先不应该实现IDisposable)。这意味着一旦您在控制器中覆盖 Dispose(bool),您将(正确地)再次看到此警告弹出窗口。

我的最佳猜测是MessageController 覆盖Dispose(bool)MessageController 派生自覆盖Dispose(bool) 的自定义基类。

请注意,您的控制器几乎不应该有 dispose 逻辑:

  • 控制器应该只处理表示逻辑,这意味着任何其他逻辑都应该被提取到您注入控制器的另一个类中。
  • 应用程序组件(例如控制器)不应释放任何传入的依赖项;这是您的 DI 容器应该为您处理的事情。

在极少数情况下控制器实际上应该自行处理,您可以覆盖该特定控制器的默认注册并将其注册为作用域。这将确保控制器在请求结束时被释放。

因此,RegisterMvcControllers 方法为您实现了这个丑陋的 hack,解决了 ASP.NET Core MVC 中的这个设计怪癖。

【讨论】:

  • 人力资源部。我在我的 InitializeContainer(app) 方法中调用 RegisterMvcControllers。我的错把它排除在最初的问题之外。我会添加它以提高知名度。也就是说,它的行为似乎不像你描述的那样。
  • @Necoras 你的 MessageController 是否覆盖了Dispose(bool)
  • 不,它是一个非常简单的 API 控制器。它具有构造函数、Get、Delete、Post 方法和一个额外的非标准 GetCount。
  • @Necoras 我不确定出了什么问题。 Here 是一个不会引发异常的工作示例。
  • @Necoras:我创建了一个新的干净的 ASP.NET Core 项目,它依赖于 SimpleInjector.Integration.AspNetCore.Mvc 3.3.0。在我复制粘贴您的确切代码并添加MessageController 之后,一切正常。只有在我添加了自定义处置逻辑之后,我才会得到与你得到的完全相同的异常。
猜你喜欢
  • 2012-04-16
  • 1970-01-01
  • 1970-01-01
  • 2022-07-23
  • 2015-03-29
  • 2019-08-08
  • 1970-01-01
  • 2020-07-07
  • 2018-10-27
相关资源
最近更新 更多