2016-12-27 22 views
2

我正在尝试使用Simple Injector创建一个.net核心WebApi服务。在我的Startup.cs我有这个:使用Simple Injector的asp.net Core Web API服务的正确DefaultScopedLifestyle是什么?

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()步以下错误消息的服务:

{“的配置无效以下诊断警告报道: - [一次性暂态] MessageController被注册为短暂的,但实现IDisposable 请参阅有关警告的详细信息的错误性质请参阅https://simpleinjector.org/diagnostics如何解决问题,如何抑制各个警告“}

- 。[一次性暂态] MessageController注册为短暂的,但实现了IDisposable。 该配置无效。报告了以下诊断警告: 有关警告的详细信息,请参阅Error属性。请参阅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(); 
} 

但问题是,现在我必须去和抑制每增加控制器警告。这不应该由默认生活方式来处理吗?

+0

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

回答

2

谈到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,简单注射器警告,因为它看到需要处置的瞬态部件,因为简单注射器不会为您配置瞬变(因为并不总是有一个可用范围,瞬态可以是存储以供以后处置)。

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

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

我最好的猜测是,要么MessageController覆盖Dispose(bool)MessageController从覆盖Dispose(bool)一个自定义的基类派生。

请注意,您的控制器应未落已配置逻辑:

  • 控制器应该只处理表示逻辑,这意味着任何其他逻辑应被提取到您注入到控制器的类。
  • 应用程序组件(如控制器)不应该处理任何传入的依赖关系;这是你的DI容器应该为你处理的东西。

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

因此,RegisterMvcControllers方法在ASP.NET Core MVC的这个设计怪癖中为你实现了这个丑陋的黑客攻击。

+0

Hrm。我在我的InitializeContainer(app)方法中调用RegisterMvcControllers。我最初的问题让我感到失望。我会将其添加到可见性中。这就是说,它似乎没有像你所描述的那样行事。 – Necoras

+0

@Necoras你的MessageController是否可以重写'Dispose(bool)'? – Steven

+0

不,这是一个非常直接的API控制器。它具有构造函数,获取,删除,发布以及其他非标准GetCount的方法。 – Necoras

相关问题