前言

近段时间在准备公司的技术分享,所以这段时间将大部分时间放在准备分享内容上去了。博客也就停了一下下。

在.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的另一个重载方法。

  1. 先将实现类注册一下
  2. 然后再注册一下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中处理一个接口多个不同实现的依赖注入问题的更多相关文章

  1. 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 ...

  2. .NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了

    最近有个需求就是一个抽象仓储层接口方法需要SqlServer以及Oracle两种实现方式,为了灵活我在依赖注入的时候把这两种实现都给注入进了依赖注入容器中,但是在服务调用的时候总是获取到最后注入的那个 ...

  3. ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)

    在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入,本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入. P ...

  4. 如何在ASP.NET Core中实现一个基础的身份认证

    注:本文提到的代码示例下载地址> How to achieve a basic authorization in ASP.NET Core 如何在ASP.NET Core中实现一个基础的身份认证 ...

  5. 在ASP.NET Core中实现一个Token base的身份认证

    注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and authorization in ASP.NET Core 在 ...

  6. [转]如何在ASP.NET Core中实现一个基础的身份认证

    本文转自:http://www.cnblogs.com/onecodeonescript/p/6015512.html 注:本文提到的代码示例下载地址> How to achieve a bas ...

  7. [转]NET Core中实现一个Token base的身份认证

    本文转自:http://www.cnblogs.com/Leo_wl/p/6077203.html 注:本文提到的代码示例下载地址> How to achieve a bearer token ...

  8. NET Core中实现一个Token base的身份认证

    NET Core中实现一个Token base的身份认证 注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and au ...

  9. Dora.Interception,为.NET Core度身打造的AOP框架 [4]:与依赖注入框架的无缝集成

    Dora.Interception最初的定位就是专门针对.NET Core的AOP框架,所以在整个迭代过程中我大部分是在做减法.对于.NET Core程序开发来说,依赖注入已经成为无处不在并且“深入骨 ...

随机推荐

  1. NSData 与 NSString 的转化

    1 NSString * str = @"hello, world!"; 2 NSData * data = [str dataUsingEncoding:NSUTF8String ...

  2. PHP Extension开发(Zephir版本)

    上篇介绍了C语言开发PHP扩展的方法, 现在介绍使用Zephir开发扩展的方法. 关于Zephir需要简单介绍一下: Zephir 是为PHP开发人员提供的能够编写可编译/静态类型的高级语言.是优秀的 ...

  3. Jenkins gitlab vue,angular,react 自动化构建【原】

    大致思路,(本篇主要讲vue ,当然了 angular react 也是一样配置) ,转发请注明原链接,谢谢 :) 1. 服务器上面配置jenkins (安装配置,不介绍) 2.新建item 自由风格 ...

  4. Python自动化--语言基础5--面向对象、迭代器、range和切片的区分

    面向对象 一.面向对象代码示例: 1 class Test(): #类的定义 2 car = "buick" #类变量,定义在类里方法外,可被对象直接调用,具有全局效果 3 def ...

  5. Java经典编程题50道之六

    输入两个正整数m和n,求其最大公约数和最小公倍数. public class Example06 {    public static void main(String[] args) {       ...

  6. 知识点干货--讲一讲final、finally、finalize的区别

    "横看成岭侧成峰,远近高低各不同.不识庐山真面目,只缘身在此山中." 这首诗来自于宋朝苏轼<题西林壁>,它的意思是,庐山从正面看,它是一道道连绵起伏的山岭:从侧面看,它 ...

  7. 用yii2给app写接口(下)

    上一节里我们讲了如何用Yii2搭建一个能够给App提供数据的API后台应用程序.那么今天我们就来探讨下授权认证和通过API接口向服务器提交数据以及如何控制API接口返回那些数据,不能返回那些数据. 授 ...

  8. Https访问

    Let's Encrypt是很火的一个免费SSL证书发行项目,自动化发行证书,证书有90天的有效期.适合个人使用或者临时使用,不用再忍受自签发证书不受浏览器信赖的提示.去年VPS侦探曾经说过Let's ...

  9. PHP opcache扩展安装

    下面是我在PHP 5.4下的安装方法: https://pecl.php.net/get/zendopcache-7.0.5.tgz tar xzf zendopcache-7.0.5.tgz cd ...

  10. 洛谷P3375 - 【模板】KMP字符串匹配

    原题链接 Description 模板题啦~ Code //[模板]KMP字符串匹配 #include <cstdio> #include <cstring> int cons ...