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

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

内容简介:用工厂模式解决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();
    }
}

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

查看所有标签

猜你喜欢:

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

编程之法

编程之法

July / 人民邮电出版社 / 2015-9-1 / 49.00元

本书涉及面试、算法、机器学习三个主题。书中的每道编程题目都给出了多种思路、多种解法,不断优化、逐层递进。本书第1章至第6章分别阐述字符串、数组、树、查找、动态规划、海量数据处理等相关的编程面试题和算法,第7章介绍机器学习的两个算法—K近邻和SVM。此外,每一章都有“举一反三”和“习题”,以便读者及时运用所学的方法解决相似的问题,且在附录中收录了语言、链表、概率等其他题型。书中的每一道题都是面试的高......一起来看看 《编程之法》 这本书的介绍吧!

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

URL 编码/解码

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

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具