2017-05-24 74 views
0

我有一箇中間件庫,我打算在多個項目中使用它。中間件本身看起來是這樣的:將注入器注入中間件依賴關係

public SdkMiddleware(RequestDelegate next, ILogger<SdkMiddleware> logger, ISdk sdk) 
{ 
    this.next = next; 
    this.logger = logger; 
    this.sdk = agentSdk; 

    this.sdk.Init(); 
    ... 
} 

由於DI,我可以簡單地注入我的記錄:

// Would rather this class be internal... 
public class Sdk: ISdk 
{ 
    private ILogger<Sdk> logger; 
    public Sdk(ILogger<Sdk> logger) 
    { 
     this.logger = logger; 
    } 

    public void Init() { 
     this.logger.Info(...) // Do some logging 
    } 

這樣做的缺點是我的類需要在每一個ASP.Net項目的Startup.cs登記:

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddTransient<ISdk, Sdk>(); 

是最好的/唯一的路線?每次我想要將一個記錄器注入一個類,我需要在我的組合根目錄中註冊該類的DI。

+0

看看內存緩存怎麼註冊自己[這裏](https://github.com/aspnet/Caching/blob/dev/src/Microsoft.Extensions.Caching.Memory/MemoryCacheServiceCollectionExtensions.cs#L22-L33) – Tseng

回答

2

使您的庫的使用者在組合根中爲此庫創建依賴關係沒有任何問題。這就是依賴注入的工作原理。您當然可以提供一些默認實現和自定義擴展方法,將這些默認實現註冊到DI中,然後讓消費者簡單地調用您的擴展方法。

+0

的確如此是框架本身使用的模式。 – ssmith

+0

自定義擴展方法是一個很好的主意 - 讓我在內部實現具體實現,但仍然將它們註冊在我的組合根目錄中。 –

1

有幾件事情,我覺得需要澄清一下:

控制

要了解什麼是依賴注入的好處(DI)最好是看原則

依賴注入/反轉DI實現的控制反轉(IoT)。 就你而言,你希望SdkMiddleware類包含對ILogger實現的引用。最簡單的方法是爲SdkMiddleware類創建一個實現ILogger接口的類的實例。這種方法的缺點是SdkMiddleware需要知道哪個類實現了ILogger接口以及如何實例化它。換句話說,SdkMiddleware控制着ILogger對象的創建。當知道哪個類實現ILogger以及如何創建實例的責任從SdkMiddleware轉移到其他類(DI中的依賴容器)和實例(如果提供給SdkMiddleware使用(通過DI注射)。在這種情況下,對創建ILogger對象的控制在SdkMiddleware之外。由於這改變了控制方向,所以稱爲「控制反轉」。 這種方法的好處是,當您需要提供另一個ILogger實現或更改創建該類實例的方式時,您根本不需要更改SdkMiddleware。

自舉

所以現在我們澄清爲什麼我們使用DI,讓我們來看看有哪些我們需要使用它。 創建所有實例的對象,控制將哪個對象注入到哪個對象中並將準備好使用對象的對象稱爲DI容器或IoT容器。在asp.net核心中,「IServiceCollection服務」用作這樣的容器。但它仍然需要知道如何創建對象以及爲哪個接口注入哪個實現。這是引導進來的地方。 在引導程序類或方法中,您需要指定如何從類構建對象以及類如何與接口相關。作爲前者的一個例子,假設您需要將數據庫的連接字符串從配置傳遞到創建數據庫連接的類。至於後者,這正是你的行「services.AddTransient()」所做的。

答案

我很抱歉花了這麼久纔給你的問題的實際答案,但我想先提供一些概述。 您是否需要指定類和接口之間的關係以將記錄器插入到類中?不可以。您的類甚至可能沒有接口,DI容器將默認注入所有依賴項,如果您要求類的對象而不是接口的實例。您還可以使用或定義一些約定而不是配置解決方案,以便類和接口的綁定將自動發生。 底線是一個類的註冊和實際的注入沒有連接。但是您提供的代碼是執行此操作的默認方式。