在.NET Core中处理一个接口多个不同实现的依赖注入问题
前言
近段时间在准备公司的技术分享,所以这段时间将大部分时间放在准备分享内容上去了。博客也就停了一下下。
在.NET Core中处理依赖注入问题时,往往是定义好了一个操作规范的接口,会有N多个基于不同技术的实现,根据实际情况在项目中去使用某一个实现。
但是偶尔会出现这样的情况,在某一个地方,需要同时使用到两种或两种以上的实现,这个时候我们要怎么处理呢?
借助Autofac等第三方组件时,是可以很容易的实现,但是在写一些基础类库时会避免直接引用太多依赖组件。
所以这里是只用微软自带的DI(Microsoft.Extensions.DependencyInjection)去处理。
例子引入
现在有一个接口和两个实现类。
public interface IDemoService
{
string Get();
}
public class DemoServiceA : IDemoService
{
public string Get()
{
return "Service A";
}
}
public class DemoServiceB : IDemoService
{
public string Get()
{
return "Service B";
}
}
常规的方法,我们先在Startup中的ConfigureServices方法中添加我们的service。
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDemoService, DemoServiceA>();
services.AddSingleton<IDemoService, DemoServiceB>();
services.AddMvc();
}
然后在控制器中使用
private IDemoService _serviceA;
private IDemoService _serviceB;
public ValuesController(IDemoService serviceA, IDemoService serviceB)
{
_serviceA = serviceA;
_serviceB = serviceB;
}
// GET api/values
[HttpGet]
public string Get()
{
return $"{_serviceA.Get()}-{_serviceB.Get()}";
}
我们的预期结果是:Service A-Service B,可是上面代码的实际结果却并不像我们想的那么简单!!

可以看到这里输出的都是Service B,连Service A的影子都没有看到。
其实,从代码都可以看出来,它只能拿到其中一个Service的实现类!
那么我们要息怎样处理才能达到我们想要的效果呢?
其实思路比较简单,上面导致不能拿到对应实现类,本质上来讲应该说是它区分不了那个才是想要的!我们想个办法让它能区分就好了。
处理方法
给我们的Service起个别名!
先是Startup中的ConfigureServices方法。
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<DemoServiceA>();
services.AddSingleton<DemoServiceB>();
services.AddSingleton(factory =>
{
Func<string, IDemoService> accesor = key =>
{
if (key.Equals("ServiceA"))
{
return factory.GetService<DemoServiceA>();
}
else if (key.Equals("ServiceB"))
{
return factory.GetService<DemoServiceB>();
}
else
{
throw new ArgumentException($"Not Support key : {key}");
}
};
return accesor;
});
services.AddMvc();
}
这里并没有直接向上面那样一次性指定接口和对应的实现类,而是用了AddSingleton的另一个重载方法。
- 先将实现类注册一下
- 然后再注册一下
Func<string, IDemoService>
先来说说这个Func<string, IDemoService>里面的string和IDemoService都分别代表什么。
- string 毫无疑问就是我们上面说到的别名
- IDemoService 这个就是我们要用的Service
核心在于,factory参数是IServiceProvider类型的!所以我们可以根据这个factory去找到我们前面注册的实现类。这样解释一下,是不是就清晰了呢?
然后再来看看在控制器上面怎么用。
private IDemoService _serviceA;
private IDemoService _serviceB;
private readonly Func<string, IDemoService> _serviceAccessor;
public ValuesController(Func<string, IDemoService> serviceAccessor)
{
this._serviceAccessor = serviceAccessor;
_serviceA = _serviceAccessor("ServiceA");
_serviceB = _serviceAccessor("ServiceB");
}
// GET api/values
[HttpGet]
public string Get()
{
return $"{_serviceA.Get()}-{_serviceB.Get()}";
}
最后看看结果是不是和我们的预期一样。

结果与预期一致。
总结
一对一,或许是最好的方法,也是最为理想的,这样能避开很多不必要的问题。但是现实中总会出现特殊情况,面对这些特殊情况,我们也是需要能够重容的面对。
如果您有更好的处理方法,也可以留言讨论。
文中的示例代码 DIDemo
在.NET Core中处理一个接口多个不同实现的依赖注入问题的更多相关文章
- ExpandoObject与DynamicObject的使用 RabbitMQ与.net core(一)安装 RabbitMQ与.net core(二)Producer与Exchange ASP.NET Core 2.1 : 十五.图解路由(2.1 or earler) .NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了
ExpandoObject与DynamicObject的使用 using ImpromptuInterface; using System; using System.Dynamic; names ...
- .NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了
最近有个需求就是一个抽象仓储层接口方法需要SqlServer以及Oracle两种实现方式,为了灵活我在依赖注入的时候把这两种实现都给注入进了依赖注入容器中,但是在服务调用的时候总是获取到最后注入的那个 ...
- ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)
在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入,本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入. P ...
- 如何在ASP.NET Core中实现一个基础的身份认证
注:本文提到的代码示例下载地址> How to achieve a basic authorization in ASP.NET Core 如何在ASP.NET Core中实现一个基础的身份认证 ...
- 在ASP.NET Core中实现一个Token base的身份认证
注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and authorization in ASP.NET Core 在 ...
- [转]如何在ASP.NET Core中实现一个基础的身份认证
本文转自:http://www.cnblogs.com/onecodeonescript/p/6015512.html 注:本文提到的代码示例下载地址> How to achieve a bas ...
- [转]NET Core中实现一个Token base的身份认证
本文转自:http://www.cnblogs.com/Leo_wl/p/6077203.html 注:本文提到的代码示例下载地址> How to achieve a bearer token ...
- NET Core中实现一个Token base的身份认证
NET Core中实现一个Token base的身份认证 注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and au ...
- Dora.Interception,为.NET Core度身打造的AOP框架 [4]:与依赖注入框架的无缝集成
Dora.Interception最初的定位就是专门针对.NET Core的AOP框架,所以在整个迭代过程中我大部分是在做减法.对于.NET Core程序开发来说,依赖注入已经成为无处不在并且“深入骨 ...
随机推荐
- 2018/1/19 Netty学习笔记(一)
这段时间学了好多好多东西,不过更多是细节和思想上的,比如分布式事物,二次提交,改善代码质量,还有一些看了一些源码什么的; 记录一下真正的技术学习,关于Netty的学习过程; 首先说Netty之前先说一 ...
- 一个Windows下线程池的实现(C++)
前言 本文配套代码:https://github.com/TTGuoying/ThreadPool 先看看几个概念: 线程:进程中负责执行的执行单元.一个进程中至少有一个线程. 多线程:一个进程中有多 ...
- MySQL数据类型概念
关系型数据库的特点 1,数据以表格的形式出现 2,每行为各种记录的名称 3,每列为数据名称所对应的数据域 4许多的行和列组成一张table 5若干的表单组成databases 术语 数据库:关联表的集 ...
- 本地Linux服务器上配置Git
当我们需要拉取远程服务器代码到本地服务器时,我们首先要确定已经配置了正确的Git账号,可以从~/.gitconfig文件(为隐藏文件,需要使用ls -a查看),以及~/.ssh下的id_rsa.pub ...
- My97DatePicker选择两个日期范围不超过30天的demo
需求 ExtJs下使用My97DatePicker对时间范围不超过30天进行选择. 关键点 使用全局变量. 对选择完的第一个日期进行逻辑判断.(我的逻辑能力还有待加强啊) 因为当选择了第一个框范围在超 ...
- [Python Study Notes]psutil模块
系统性能信息模块psutil psutil是一个跨平台库,能够轻松实现获取系统运行的进程和系统利用率(CPU,内存,磁盘,网络等)信息,主要应用于系统监控,分析和限制系统资源及进程的管理,它实现了同等 ...
- Ubuntu下利用Apache转发模块实现反向代理
Apache的反向代理主要利用转发模块,proxy和proxy_http 先配置 Apache 支持proxy 和 proxy_http 在Ubuntu系统下,Apache的配置文件在目录/etc/a ...
- window 下生成NodeJs(v8.9.3) 的 VS2015 解决方案node.sln
window 下生成NodeJs(v8.9.3) 的 VS2015 解决方案node.sln 使用步骤 也可以参照 github: https://github.com/nodejs/node/blo ...
- Linux 安装配置 FTP 服务 (vsftpd)
1. 安装 vsftpd yum install vsftpd -y 2. 创建用户 record adduser -s /bin/nologin -d /var/RecordFile/ record ...
- Java经典编程题50道之二十七
求100之内的素数. public class Example27 { public static void main(String[] args) { prime(); } ...