依賴注入


layout: docs-default

依賴注入

這一節(jié)的例子可以看 here

IdentityServer3 有很多擴展點支持不同的服務(wù)。默認的服務(wù)實現(xiàn)設(shè)計成相互解耦,可以獨立替換。為了實現(xiàn)這個目標,我們使用依賴注入來把所有的服務(wù)組裝起來。

注入 IdentityServer 服務(wù)

如果需要,IdentityServer托管程序可以替換默認服務(wù)。自定義的服務(wù)實現(xiàn)也可以使用依賴注入,IdentityServer的類型和用戶自定義的類型都可以注入。注意,注入只支持通過Registration注冊的服務(wù)和存儲。
對于使用IdentityServer類型的自定義服務(wù),可以在構(gòu)造函數(shù)里指定依賴關(guān)系。
當IdentityServer實例化注冊的類型時,構(gòu)造函數(shù)里的參數(shù)會被自動構(gòu)建。比如:

public class MyCustomTokenSigningService: ITokenSigningService
{
    private readonly IdentityServerOptions _options;

    public MyCustomTokenSigningService(IdentityServerOptions options)
    {
        _options = options;
    }

    public Task<string> SignTokenAsync(Token token)
    {
        // ...
    }
}

用如下方法注冊:

var factory = new IdentityServerServiceFactory();
factory.TokenSigningService = new Registration<ITokenSigningService>(typeof(MyCustomTokenSigningService));

或者使用簡化語法:

var factory = new IdentityServerServiceFactory();
factory.TokenSigningService = new Registration<ITokenSigningService, MyCustomTokenSigningService>();

注入自定義服務(wù)

你的自定義服務(wù)可能依賴于你自己的類型。
通過在IdentityServer的依賴注入系統(tǒng)中配置,自定義的類型也可以注入。
通過使用IdentityServerServiceFactoryRegister()方法來實現(xiàn),比如:如果需要把自定義的日志服務(wù)注入到自己的服務(wù)里面:

public interface ICustomLogger
{
    void Log(string message);
}

public class DebugLogger : ICustomLogger
{
    public void Log(string message)
    {
        Debug.WriteLine(message);
    }
}

public class MyCustomTokenSigningService: ITokenSigningService
{
    private readonly IdentityServerOptions _options;
    private readonly ICustomLogger _logger;

    public MyCustomTokenSigningService(IdentityServerOptions options, ICustomLogger logger)
    {
        _options = options;
        _logger = logger;
    }

    public Task<string> SignTokenAsync(Token token)
    {
        // ...
    }
}

為了注入ICustomLogger,我們需要等級ICustomLogger和MyCustomDebugLogger的關(guān)系:

var factory = new IdentityServerServiceFactory();
factory.TokenSigningService = new Registration<ITokenSigningService, MyCustomTokenSigningService>();
factory.Register(new Registration<ICustomLogger, MyCustomDebugLogger>());

沒有接口的服務(wù)

上面的例子我們注入了 ICustomLogger ,它的實現(xiàn)是 MyCustomDebugLogger.如果自定義服務(wù)沒有設(shè)計成接口實現(xiàn)分離的方式,我們可以直接注冊實體類型來注入。

例如: MyCustomTokenSigningService的構(gòu)造函數(shù)不接受日志接口類型,而是接受日志實體類型。

public class MyCustomTokenSigningService: ITokenSigningService
{
    public MyCustomTokenSigningService(IdentityServerOptions options, MyCustomDebugLogger logger)
    {
        _options = options;
        _logger = logger;
    }

    // ...
}

我們需要把實體類型注入配置成下面的樣子:

var factory = new IdentityServerServiceFactory();
factory.TokenSigningService = new Registration<ITokenSigningService, MyCustomTokenSigningService>();
factory.Register(new Registration<MyCustomDebugLogger>());

簡單說,上面的注冊方式意味著MyCustomDebugLogger實體類會被注入到依賴的服務(wù)中。

自定義類型創(chuàng)建

如果自定義服務(wù)需要手動構(gòu)建(比如有些特殊的參數(shù)必須自己配置,不能依賴于注入),這時候,我們可以用Registration類,傳入一個工廠回調(diào)函數(shù),這個Registration構(gòu)造方法前面如下:

new Registration<T>(Func<IDependencyResolver, T> factory) 

這個回調(diào)函數(shù)必須返回一個實現(xiàn)T接口的對象,如下代碼:

var factory = new IdentityServerServiceFactory();
factory.TokenSigningService = new Registration<ITokenSigningService>(resolver =>
    new MyCustomTokenSigningService("SomeSigningKeyValue")
);

獲取其它依賴

上面的方法已經(jīng)很靈活啦,但是你可能需要更精巧的依賴注入。比如你可能依賴于其它服務(wù)。這時候IDependencyResolver開始展現(xiàn)威力啦。它允許你從回調(diào)函數(shù)中取到服務(wù)。比如,你自定義的客戶端存儲依賴于來自IdentityServer的另一個服務(wù),他可以用下面的方式來得到:

var factory = new IdentityServerServiceFactory();
factory.TokenSigningService = new Registration<ITokenSigningService>(resolver =>
    new MyCustomTokenSigningService("SomeSigningKeyValue", resolver.Resolve<ICustomLogger>())
);

命名依賴

最后,當我們通過IdentityServerServiceFatoryRegister()方法注冊依賴時,我們可以給這個依賴名字。這個名字通過Registeration構(gòu)造函數(shù)的name參數(shù)來指定。這個只用于自定義注冊的以來,這個名字也只能在自定義服務(wù)里面,使用IDependencyResolver方法解決依賴時使用。
命名依賴在一個T接口有多個實現(xiàn)時特別有用,比如:

string mode = "debug"; // or "release", for example

var factory = new IdentityServerServiceFactory();

factory.Register(new Registration<ICustomLogger, MyFileSystemLogger>("debug"));
factory.Register(new Registration<ICustomLogger, MyDatabaseLogger>("release"));

factory.TokenSigningService = new Registration<ITokenSigningService>(resolver =>
    new MyCustomTokenSigningService(resolver.Resolve<ICustomLogger>(mode))
);

這個例子中mode做為配置項,決定了運行的時候到底使用哪一個ICustomLogger具體實現(xiàn)。

注冊模式的實例化

Registration 類允許服務(wù)指定一個服務(wù)有多少個實例可以創(chuàng)建,Mode屬性是一個枚舉,可選值如下:

  • InstancePerHttpRequest
    每次請求創(chuàng)建一個實例。這意味著如果服務(wù)在一次請求中,申請了兩次某個依賴,會得到同樣的實例。
  • InstancePerUse
    為服務(wù)里每次獨立的請求創(chuàng)建一個實例。也就是說如果自定義服務(wù)在不同的代碼段請求了某個依賴,那么會得到不同的實例。
  • Singleton
    只有一個實例會被創(chuàng)建。當傳給Registration構(gòu)造函數(shù)一個單例對象的時候,這個模式會自動啟用。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容