用工厂模式解决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 _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中依赖注入的一个烦恼的更多相关文章
- ASP.NET Core之依赖注入
本文翻译自:http://www.tutorialsteacher.com/core/dependency-injection-in-aspnet-core ASP.NET Core支持依赖注入,依赖 ...
- 几十行代码实现ASP.NET Core自动依赖注入
在开发.NET Core web服务的时候,我们习惯使用自带的依赖注入容器来进行注入. 于是就会经常进行一个很频繁的的重复动作:定义一个接口->写实现类->注入 有时候会忘了写Add这一步 ...
- 如何解决 ASP.NET Core 中的依赖问题
依赖性注入是一种技术,它允许我们注入一个特定类的依赖对象,而不是直接创建这些实例. 使用依赖注入的好处显而易见,它通过放松模块间的耦合,来增强系统的可维护性和可测试性. 依赖注入允许我们修改具体实现, ...
- 【ASP.NET Core】依赖注入高级玩法——如何注入多个服务实现类
依赖注入在 ASP.NET Core 中起中很重要的作用,也是一种高大上的编程思想,它的总体原则就是:俺要啥,你就给俺送啥过来.服务类型的实例转由容器自动管理,无需我们在代码中显式处理. 因此,有了依 ...
- Asp.net core自定义依赖注入容器,替换自带容器
依赖注入 在asp.net core程序中,众所周知,依赖注入基本上贯穿了整个项目,以通用的结构来讲解,控制器层(Controller层)依赖业务层(Service层),业务层依赖于仓储层(Repos ...
- asp.net core ioc 依赖注入
1.生命周期 内置的IOC有三种生命周期: Transient: Transient服务在每次被请求时都会被创建.这种生命周期比较适用于轻量级的无状态服务. Scoped: Scoped生命周期的服务 ...
- ASP.NET Core:依赖注入
ASP.NET Core的底层设计支持和使用依赖注入.ASP.NET Core应用程序可以利用内置的框架服务将它们注入到启动类的方法中,并且应用程序服务能够配置注入.由ASP.NET Core提供的默 ...
- .NET Core 中依赖注入框架详解 Autofac
本文将通过演示一个Console应用程序和一个ASP.NET Core Web应用程序来说明依赖注入框架Autofac是如何使用的 Autofac相比.NET Core原生的注入方式提供了强大的功能, ...
- .NET Core 中依赖注入 AutoMapper 小记
最近在 review 代码时发现同事没有像其他项目那样使用 AutoMapper.Mapper.Initialize() 静态方法配置映射,而是使用了依赖注入 IMapper 接口的方式 servic ...
随机推荐
- Sequel Pro for Mac(MySQL 数据库管理工具)破解版安装
1.软件简介 Sequel Pro 是一款管理 Mysql 的工具,界面简洁易用. 2.功能特色 FULL MYSQL SUPPORT Sequel Pro is a fast, easy-to ...
- Swift Assert 断言
前言 对每次运行都会出现的错误通常不会过于苦恼,可以使用断点调试或者 try catch 之类的方式判断并修复它.但是一些偶发(甚至是无数次运行才会出现一次)的错误单靠断点之类的方式是很难排除掉的,为 ...
- 《网络编程》IPv4 与 IPv6 相互操作
前言 因为互联网终端不断添加.IPv4 地址长度(32位)已不可以满足要求.所以出现了 IPv6地址(128位).可是现有应用程序大部分还是採用 IPv4 地址形式,所以必须解决 IPv4 与 IPv ...
- 《转》vue更新到2.0之后vue-resource不在更新,axios的使用
vue更新到2.0之后,作者就宣告不再对vue-resource更新,而是推荐的axios,前一段时间用了一下,现在说一下它的基本用法. 首先就是引入axios,如果你使用es6,只需要安装axios ...
- RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较(转)
RabbitMQ中,所有生产者提交的消息都由Exchange来接受,然后Exchange按照特定的策略转发到Queue进行存储 RabbitMQ提供了四种Exchange:fanout,direct, ...
- 100种不同图片切换效果插件pageSwitch
分享100种不同图片切换效果插件pageSwitch.这是一款适用于全屏切换场景,即一切一屏,并且实现了超过一百种切换效果,支持自定义切页动画.效果图如下: 在线预览 源码下载 实现的代码. ht ...
- 教你一招:win10下JDK的安装与环境变量配置
1.到官网下载最新版本的JDK http://www.oracle.com/technetwork/java/javase/downloads/index.html 2.安装JDK,同安装其他软件一样 ...
- Java知多少(82)标签、按钮和按钮事件简介
标签和按钮也许是图形界面中最常见的两种组件,按钮又总是与激发动作事件有关. 标签 标签(JLabel)是最简单的Swing组件.标签对象的作用是对位于其后的界面组件作说明.可以设置标签的属性,即前景色 ...
- Nginx配置详细
######Nginx配置文件nginx.conf中文详解##### #定义Nginx运行的用户和用户组 user www www; #nginx进程数,建议设置为等于CPU总核心数. worker_ ...
- 简单的SSM框架搭建教程
简单的ssm框架的搭建和配置文件 ssm框架里边的配置: 1.src路径下直接存放数据库和log4j的properties文件 2.src路径下建个config包,分别放置ssm的xml文件 3.修改 ...