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

用工厂模式解决ASP.NET Core中依赖注入的一个烦恼的更多相关文章

  1. ASP.NET Core之依赖注入

    本文翻译自:http://www.tutorialsteacher.com/core/dependency-injection-in-aspnet-core ASP.NET Core支持依赖注入,依赖 ...

  2. 几十行代码实现ASP.NET Core自动依赖注入

    在开发.NET Core web服务的时候,我们习惯使用自带的依赖注入容器来进行注入. 于是就会经常进行一个很频繁的的重复动作:定义一个接口->写实现类->注入 有时候会忘了写Add这一步 ...

  3. 如何解决 ASP.NET Core 中的依赖问题

    依赖性注入是一种技术,它允许我们注入一个特定类的依赖对象,而不是直接创建这些实例. 使用依赖注入的好处显而易见,它通过放松模块间的耦合,来增强系统的可维护性和可测试性. 依赖注入允许我们修改具体实现, ...

  4. 【ASP.NET Core】依赖注入高级玩法——如何注入多个服务实现类

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

  5. Asp.net core自定义依赖注入容器,替换自带容器

    依赖注入 在asp.net core程序中,众所周知,依赖注入基本上贯穿了整个项目,以通用的结构来讲解,控制器层(Controller层)依赖业务层(Service层),业务层依赖于仓储层(Repos ...

  6. asp.net core ioc 依赖注入

    1.生命周期 内置的IOC有三种生命周期: Transient: Transient服务在每次被请求时都会被创建.这种生命周期比较适用于轻量级的无状态服务. Scoped: Scoped生命周期的服务 ...

  7. ASP.NET Core:依赖注入

    ASP.NET Core的底层设计支持和使用依赖注入.ASP.NET Core应用程序可以利用内置的框架服务将它们注入到启动类的方法中,并且应用程序服务能够配置注入.由ASP.NET Core提供的默 ...

  8. .NET Core 中依赖注入框架详解 Autofac

    本文将通过演示一个Console应用程序和一个ASP.NET Core Web应用程序来说明依赖注入框架Autofac是如何使用的 Autofac相比.NET Core原生的注入方式提供了强大的功能, ...

  9. .NET Core 中依赖注入 AutoMapper 小记

    最近在 review 代码时发现同事没有像其他项目那样使用 AutoMapper.Mapper.Initialize() 静态方法配置映射,而是使用了依赖注入 IMapper 接口的方式 servic ...

随机推荐

  1. Hadoop2.2.0分布式安装配置详解[2/3]

    前言 本文主要通过对hadoop2.2.0集群配置的过程加以梳理,所有的步骤都是通过自己实际测试.文档的结构也是根据自己的实际情况而定,同时也会加入自己在实际过程遇到的问题.搭建环境过程不重要,重要点 ...

  2. 基于Centos搭建个人 Leanote 云笔记本

    系统要求:CentOS 7.2 64 位操作系统 下载启动 MongoDB Leanote 依赖 MongoDB 作为数据存储,下面开始安装 MongoDB: 下载 MongoDB 进入 /home  ...

  3. RDLC 图形报表预览时 “本地报表处理期间错误”

    在RDLC报表中有图形报表的导出和打印都正常,但预览时"本地报表处理期间错误",这是因为你设置的图形太宽已经超过默认的A4 纸的宽度,解决办法:报表页面的报表--->报表属性 ...

  4. nginx(一)下载和启动

    一.准备工作 http://nginx.org/en/download.html 下载,解压,配置,编译,安装,都用默认的设置即可. 二.安装完成后 默认的安装路径为 /usr/local/nginx ...

  5. 为什么要用 Node.js

    每日一篇优秀博文 2017年10月10日 周二 为什么要用 Node.js 这是一个移动端工程师涉足前端和后端开发的学习笔记,如有错误或理解不到位的地方,万望指正. Node.js 是什么 传统意义上 ...

  6. Asp.Net WebApi学习教程之增删改查

    webapi简介 在asp.net中,创建一个HTTP服务,有很多方案,以前用ashx,一般处理程序(HttpHandler),现在可以用webapi 微软的web api是在vs2012上的mvc4 ...

  7. Java如何查找系统的代理设置?

    在Java编程中,如何查找系统的代理设置? 以下示例显示如何使用HttpURLConnection类的systemSetting()方法和getResponse()方法的put方法在系统上查找代理设置 ...

  8. CentOS Nginx网站服务器搭建实例

    Nginx是一款开源的高性能HTTP服务器和返向代理服务器.     下载.编译.安装模块:   [root@localhost nginx-1.4.0]#wget http://nginx.org/ ...

  9. Zookeeper+Kafka集群部署

    Zookeeper+Kafka集群部署 主机规划: 10.200.3.85  Kafka+ZooKeeper 10.200.3.86  Kafka+ZooKeeper 10.200.3.87  Kaf ...

  10. System.Runtime.InteropServices.COMException 检索COM类工厂中CLSID{xxxxxxxxx}的组件时失败解决方法

    iis7.5中设定应用程序池中<进程模型>中<标识>为localSystem 提示:System.Runtime.InteropServices.COMException: 命 ...