用原廠模式解決ASP.NET Core中依賴注入的一個煩惱

來源:互聯網
上載者:User

標籤:private   client   asp   tor   text   項目   top   icon   建構函式   

這是最近在實際開發中遇到的一個問題,用 asp.net core 開發一個後端 web api ,根據指定的 key 清除 2 台 memcached 伺服器上的緩衝。背景是我們在進行 .net core 遷移工作,asp.net 項目與 asp.net core 項目並存,為了避免兩種類型項目的緩衝衝突,我們分別用了 2 台不同的 memcached 伺服器。

之前使用 1 台 memcached 伺服器時,只需要一個用戶端,所以只需建立一個 MemcachedClient 單例並注入到 IMemcachedClient 介面。

public void ConfigureServices(IServiceCollection services){    services.AddOptions();    services.Configure<MemcachedClientOptions>(Configuration.GetSection("memcached"));    services.Add(ServiceDescriptor.Transient<IMemcachedClientConfiguration, MemcachedClientConfiguration>());    services.Add(ServiceDescriptor.Singleton<IMemcachedClient, MemcachedClient>());}

(註:memcached 的配置儲存在 appsettings.json 中)

而現在需要用 2 個 memcached 用戶端執行個體分別串連 2 台不同的 memcached 伺服器,需要 2 個不同配置的 MemcachedClient 單例,而之前針對 1 個 IMemcachedClient 介面的依賴注入方法不管用了。咋整?

首先想到的是一個變通的方法,1 個介面不行,那就用 2 個介面,於是增加下面的 2 個介面:

public interface IMemcachedClientCore : IMemcachedClient{
}public interface IMemcachedClientLegacy : IMemcachedClient{
}

因為 MemcachedClient 並沒有實現這個這 2 個介面,還要另外增加這 2 個介面的實現:

public class MemcachedClientCore : MemcachedClient, IMemcachedClientCore{    public MemcachedClientCore(        ILogger<MemcachedClient> logger,        IMemcachedClientConfiguration configuration)        : base(logger, configuration)    {    }}public class MemcachedClientLegacy : MemcachedClient, IMemcachedClientLegacy{    public MemcachedClientLegacy(        ILogger<MemcachedClient> logger,        IMemcachedClientConfiguration configuration)        : base(logger, configuration)    {    }}

沿著這條路發現越走越不對勁,還要增加更多的介面與實現。由於 2 個 memcached 用戶端的不同在於 IMemcachedClientConfiguration 的不同,而上面的  MemcachedClientCore 與  MemcachedClientLegacy 的建構函式都注入 IMemcachedClientConfiguration 是不行的,還要基於 IMemcachedClientConfiguration 再增加 2 個介面,增加了介面就又不得不再增加實現。。。這樣解決問題豈不讓人瘋掉,遂棄之。

後來轉念一想,自己解決問題的思路走偏了,一味地將關注的焦點放在如何通過 Dependency Injection 注入 2 個不同的 MemcachedClient 執行個體,而忽略了一個很簡單的解決方案 —— 用工廠類建立 MemcachedClient 執行個體,通過 Dependency Injection 注入工廠類,就像 ILoggerFactory 那樣。

於是通過基於依賴注入的原廠模式輕鬆解決了這個問題。

定義一個 IMemcachedClientFactory 介面:

public interface{    IMemcachedClientFactory Add(string keyOfConfiguration);    IMemcachedClient Create(string keyOfConfiguration);        }

添加 MemcachedClientFactory 類實現 IMemcachedClientFactory 介面:

public class MemcachedClientFactory : IMemcachedClientFactory{    private readonly ILoggerFactory _loggerFacotry;    private readonly IConfiguration _configuration;    private readonly Dictionary<string, IMemcachedClient> _clients = new Dictionary<string, IMemcachedClient>();    public MemcachedClientFactory(        ILoggerFactory loggerFacotry,        IConfiguration configuration)    {        _loggerFacotry = loggerFacotry;        _configuration = configuration;    }    public IMemcachedClientFactory Add(string keyOfConfiguration)    {        var options = new MemcachedClientOptions();        _configuration.GetSection(keyOfConfiguration).Bind(options);        var memcachedClient = new MemcachedClient(            _loggerFacotry,            new MemcachedClientConfiguration(_loggerFacotry, options));        _clients.Add(keyOfConfiguration, memcachedClient);        return this;    }    public IMemcachedClient Create(string keyOfConfiguration)    {        return _clients[keyOfConfiguration];    }}

在 Startup.ConfigureServices() 中注入 MemcachedClientFactory 的單例:

public void ConfigureServices(IServiceCollection services){    services.AddSingleton<IMemcachedClientFactory, MemcachedClientFactory>();}

在 Startup.Configure() 中調用 IMemcachedClientFactory 介面的 Add() 方法,根據不同配置建立 MemcachedClient 的執行個體:

public void Configure(IApplicationBuilder app, IMemcachedClientFactory memcachedClientFactory){    memcachedClientFactory.Add("MemcachedLegacy").Add("MemcachedCore");}

在使用  MemcachedClient 的地方通過 IMemcachedClientFactory 介面的 Create() 方法擷取所需 MemcachedClient 的執行個體:

public class CacheController : Controller{    private readonly IMemcachedClient _memcachedClientLegacy;    private readonly IMemcachedClient _memcachedClientCore;    public CacheController(IMemcachedClientFactory memcachedClientFacotry)    {        _memcachedClientLegacy = memcachedClientFacotry.Create("MemcachedLegacy");        _memcachedClientCore = memcachedClientFacotry.Create("MemcachedCore");    }    [HttpDelete("{key}")]    public async Task<IActionResult> Delete(string key)    {        var removeCoreTask =  _memcachedClientCore.RemoveAsync(key);        var removeLegacyTask = _memcachedClientLegacy.RemoveAsync(key);        await removeCoreTask;        await removeLegacyTask;        return Ok();    }}

用原廠模式解決ASP.NET Core中依賴注入的一個煩惱

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.