用工厂模式解决ASP.NET Core中依赖注入的一个烦恼

栏目: ASP.NET · 发布时间: 8年前

内容简介:用工厂模式解决ASP.NET Core中依赖注入的一个烦恼

用工厂模式解决ASP.NET Core中依赖注入的一个烦恼

这是最近在实际开发中遇到的一个问题,用 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();
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Analytics 2.0

Web Analytics 2.0

Avinash Kaushik / Sybex / 2009-10-26 / USD 39.99

The bestselling book Web Analytics: An Hour A Day was the first book in the analytics space to move beyond clickstream analysis. Web Analytics 2.0 will significantly evolve the approaches from the fir......一起来看看 《Web Analytics 2.0》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器