2016-12-27 21 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

相關問題