用工厂模式解决asp.netcore中依赖注入的一个烦恼

dudu dudu     2022-09-01     610

关键词:

这是最近在实际开发中遇到的一个问题,用 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 _loggerFactory;
    private readonly IConfiguration _configuration;
    private readonly Dictionary<string, IMemcachedClient> _clients = new Dictionary<string, IMemcachedClient>();

    public MemcachedClientFactory(
        ILoggerFactory loggerFactory,
        IConfiguration configuration)
    {
        _loggerFactory = loggerFactory;
        _configuration = configuration;
    }

    public IMemcachedClientFactory Add(string keyOfConfiguration)
    {
        var options = new MemcachedClientOptions();
        _configuration.GetSection(keyOfConfiguration).Bind(options);

        var memcachedClient = new MemcachedClient(
            _loggerFactory,
            new MemcachedClientConfiguration(_loggerFactory, 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 memcachedClientFactory)
    {
        _memcachedClientLegacy = memcachedClientFactory.Create("MemcachedLegacy");
        _memcachedClientCore = memcachedClientFactory.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();
    }
}

2.1依赖注入

...esolver附加的IShouldInitialize接口ASP.NETMVC和ASP.NETWebAPI集成ASP.NETCore 查看详情

asp.netcore依赖注入(di)(代码片段)

原文:ASP.NETCore依赖注入(DI)  ASP.NETCore的底层设计支持和使用依赖注入。ASP.NETCore应用程序可以利用内置的框架服务将服务注入到启动类的方法中,并且应用程序服务也可以配置注入。由ASP.NETCore提供的默认服务容器提供了最小... 查看详情

《asp.netcore3框架揭秘》博文汇总

在过去一段时间内,写了一系列关于ASP.NETCore3相关的文章,其中绝大部分来源于即将出版的《ASP.NETCore3框架揭秘》(博文只能算是“初稿”,与书中相应章节具有一定差异),先将它们汇总在这里。如果对《ASP.NETCore3框架揭秘》... 查看详情

asp.netcore依赖注入最佳实践——提示与技巧(代码片段)

在这篇文章,我将分享一些在ASP.NETCore程序中使用依赖注入的个人经验和建议。这些原则背后的动机如下:高效地设计服务和它们的依赖。预防多线程问题。预防内存泄漏。预防潜在的BUG。这篇文章假设你已经基本熟悉依赖注入... 查看详情

asp.netcore依赖注入问题

   最近.netcore可以跨平台了,这是一个伟大的事情,为了可以赶上两年以后的跨平台部署大潮,我也加入到了学习之列。今天研究的是依赖注入,但是我发现一个问题,困扰我很久,现在我贴出来,希望可以有人帮忙... 查看详情

如何在 ASP.NET CORE 中使用具有依赖注入的动作过滤器?

】如何在ASP.NETCORE中使用具有依赖注入的动作过滤器?【英文标题】:HowtouseActionFilterswithDependencyInjectioninASP.NETCORE?【发布时间】:2017-01-0810:35:47【问题描述】:我在我的ASP.NETCORE应用程序中到处使用基于构造函数的依赖注入,我... 查看详情

如何在 ASP.NET Core MVC 中使用依赖注入设计存储库模式?

】如何在ASP.NETCoreMVC中使用依赖注入设计存储库模式?【英文标题】:HowtodesignaRepositoryPatternwithDependencyInjectioninASP.NETCoreMVC?【发布时间】:2017-02-2100:08:41【问题描述】:作为ASP.NETCore1.0MVC的新手,我决定为MVCCore应用程序使用存储... 查看详情

《asp.netcore6框架揭秘》实例演示[04]:自定义依赖注入框架

ASP.NETCore框架建立在一个依赖注入框架之上,已注入的方式消费服务已经成为了ASP.NETCore基本的编程模式。为了使读者能够更好地理解原生的注入框架框架,我按照类似的设计创建了一个简易版本的依赖注入框架,并... 查看详情

ASP.Net Core 使用啥依赖注入框架?

】ASP.NetCore使用啥依赖注入框架?【英文标题】:WhatDependencyInjectionFrameworkDoesASP.NetCoreUse?ASP.NetCore使用什么依赖注入框架?【发布时间】:2017-08-3119:27:30【问题描述】:我开始涉足ASP.NetCore,发现依赖注入是ASP.NetCore框架中的一等... 查看详情

《asp.netcore6框架揭秘》实例演示[10]:options基本编程模式

...#xff0c;这篇文章演示几种典型的编程模式。[本文节选《ASP.NETCore6框架揭秘》第6章][601]将配置绑定为Options对象(源代码&#x 查看详情

未调用 ASP.NET Core 3 中依赖注入服务的具体实现

】未调用ASP.NETCore3中依赖注入服务的具体实现【英文标题】:ConcreteimplementationofdependencyinjectedserviceinASP.NETCore3notbeingcalled【发布时间】:2020-06-1023:20:24【问题描述】:我阅读了IntroductiontoIdentityonASP.NETCore以在我的ASP.NETCore3Web应用... 查看详情

asp.netcore自定义依赖注入容器,替换自带容器

依赖注入    在asp.netcore程序中,众所周知,依赖注入基本上贯穿了整个项目,以通用的结构来讲解,控制器层(Controller层)依赖业务层(Service层),业务层依赖于仓储层(Repository层),而其他层级中也或多或少的使用了依赖... 查看详情

[asp.netcore3框架揭秘]依赖注入:一个mini版的依赖注入框架(代码片段)

...论的角度对依赖注入进行了深入论述,我们接下来会对.NETCore依赖注入框架进行单独介绍。为了让读者朋友能够更好地理解.NETCore依赖注入框架的设计与实现,我们按照类似的原理创建了一个简易版本的依赖注入框架,也就是我... 查看详情

asp.netcore依赖注入高级玩法——如何注入多个服务实现类

...文地址:https://www.bbsmax.com/A/nAJvbK0nJr/ 依赖注入在ASP.NETCore中起中很重要的作用,也是一种高大上的编程思想,它的总体原则就是:俺要啥,你就给俺送啥过来。服务类型的实例转由容器自动管理,无需我们在代码中显式处理... 查看详情

asp.netcore依赖注入高级玩法——如何注入多个服务实现类(代码片段)

依赖注入在ASP.NETCore中起中很重要的作用,也是一种高大上的编程思想,它的总体原则就是:俺要啥,你就给俺送啥过来。服务类型的实例转由容器自动管理,无需我们在代码中显式处理。因此,有了依赖注入后,你的编程思维... 查看详情

抽象类中的依赖注入,ASP.NET Core

】抽象类中的依赖注入,ASP.NETCore【英文标题】:DependencyInjectioninabstractclass,ASP.NETCore【发布时间】:2018-09-1303:10:27【问题描述】:在我的ASP.NETCore2项目中,我创建了继承RazorPage类的新类,以在视图中添加一些额外的属性。publicabs... 查看详情

ASP.NET Core 2 中的依赖注入引发异常

】ASP.NETCore2中的依赖注入引发异常【英文标题】:DependencyinjectioninASP.NETCore2throwsexception【发布时间】:2017-10-2602:52:30【问题描述】:当我尝试在Startup.cs文件中的Configure方法中使用自定义DbContext时收到以下异常。我在2.0.0-preview1-00... 查看详情

用工厂/或构建器替换构造函数

】用工厂/或构建器替换构造函数【英文标题】:Replaceconstructorwithafactory/orabuilder【发布时间】:2011-06-0819:31:08【问题描述】:我正在使用IntelliJ10社区版,我注意到有两个相似的重构选项:-用工厂替换构造函数-将构造函数替换为... 查看详情