首页 > 其他分享 >.NET依赖注入之一个接口多个实现

.NET依赖注入之一个接口多个实现

时间:2023-02-27 13:24:38浏览次数:55  
标签:依赖 customService 实现 void 接口 ICustomService NET public

.NET依赖注入之一个接口多个实现

 

前言

最近又在项目中碰到需要将原本单实现的接口改造成多个实现的场景,这里记录一下常见的几种改法。

假设已经存在如下接口ICustomService和其实现CustomService,由于只有一种实现,注入和使用非常容易。

  public interface ICustomService
  {
  void MethodA();
  void MethodB();
  }
  public class CustomService: ICustomService
  {
  public void MethodA()
  {
  }
   
  public void MethodB()
  {
  }
  }
   
  //注入
  builder.Services.AddTransient<ICustomService, CustomService>();
   
  //使用
  private readonly ICustomService _customService;
  public CustomController(ICustomService customService)
  {
  _customService = customService;
  }

现在我们需要增加一种实现。

使用多个接口实现

我们可以将原ICustomService内的方法移到到一个新的基接口,共享出来,需要多少个实现,就创建多少个空接口继承该基接口。

  //基接口
  public interface ICustomBaseService
  {
  void MethodA();
  void MethodB();
  }
   
  //多个空接口
  public interface ICustomService : ICustomBaseService
  {
  }
   
  public interface ICustomServiceV2 : ICustomBaseService
  {
  }
   
  //第一种实现
  public class CustomService: ICustomService
  {
  public void MethodA()
  {
  }
   
  public void MethodB()
  {
  }
  }
   
  //第二种实现
  public class CustomServiceV2: ICustomServiceV2
  {
  public void MethodA()
  {
  }
   
  public void MethodB()
  {
  }
  }
   
  //注入
  builder.Services.AddTransient<ICustomService, CustomService>();
  builder.Services.AddTransient<ICustomServiceV2, CustomServiceV2>();
   
   
  //使用
  private readonly ICustomService _customService;
  private readonly ICustomServiceV2 _customServiceV2;
  public CustomController(ICustomService customService,ICustomServiceV2 customServiceV2)
  {
  _customService = customService;
  _customServiceV2 = customServiceV2;
  }

这种实现方式需要增加了一套空接口做隔离,看似可能比较“浪费”,但后期随着项目的演进,ICustomServiceICustomServiceV2可能会慢慢分化,我们可以很方便的为它们扩充各种独有方法。

使用单接口实现

如果我们确定不需要多个接口,也可以使用下面的单接口实现

  public interface ICustomService
  {
  void MethodA();
  void MethodB();
  }
   
  //第一种实现
  public class CustomService: ICustomService
  {
  public void MethodA()
  {
  }
   
  public void MethodB()
  {
  }
  }
   
  //第二种实现
  public class CustomServiceV2: ICustomService
  {
  public void MethodA()
  {
  }
   
  public void MethodB()
  {
  }
  }
   
  //注入
  builder.Services.AddTransient<ICustomService, CustomService>();
  builder.Services.AddTransient<ICustomService, CustomServiceV2>();
   
   
  //使用
  private readonly ICustomService _customService;
  private readonly ICustomService _customServiceV2;
  public CustomController(IEnumerable<ICustomService> customServices)
  {
  _customService = customServices.ElementAt(0);
  _customServiceV2 = customServices.ElementAt(1);
  }

从上面代码可以看到,我们是为从接口ICustomService注册两个实现,并从IEnumerable<ICustomService>解析出了这两个实现。这里可能会有两个疑问

  1. 为什么第一个实现CustomService没有被第二个实现CustomServiceV2替换掉?
  2. 为什么可以从IEnumerable<ICustomService>解析到我们需要的服务?

答案在Microsoft.Extensions.DependencyInjection.ServiceDescriptor 和 Microsoft.Extensions.DependencyInjection.ServiceCollection 这两个类里,进程里,依赖注入的服务,会被添加到ServiceCollection里,ServiceCollection是一组ServiceDescriptor的集合,ServiceDescriptor通过服务类型、实现以及生命周期三个组合在一起构成的标识来确定服务。而ICustomService+CustomService+TransientICustomService+CustomServiceV2+Transient是两个不同的ServiceDescriptor,因此不会被替换。同时服务类型的ServiceDescriptor会被聚合在一起,于是我们可以很方便的从IEnumerable对象中解析出所有的同类型的服务。

总结

本质上,两种方法都是多态性(Polymorphism)的应用,没有优劣之分,根据场景选择合适的写法。

链接

https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection
https://github.com/dotnet/runtime

标签:依赖,customService,实现,void,接口,ICustomService,NET,public
From: https://www.cnblogs.com/sexintercourse/p/17159320.html

相关文章

  • 我做的百度飞桨PaddleOCR .NET调用库
    我做的百度飞桨PaddleOCR.NET调用库 我做的百度飞桨PaddleOCR.NET调用库.NETConf2021中国我做了一次《.NET玩转计算机视觉OpenCV》的分享,其中提到了一个效果特别......
  • 如何将 Autofac 整合进 Net6.0 Core MVC 项目中
    一、前言1、前言Asp.NetCoreMvc,我也用了很长一段时间了,它现在的编程模型和方式还是特别棒的,都是组件开发,什么都可以替换,当然了,您别抬杠,有些还是......
  • Winform C# .Net中给ListBox加ToolTip提示
    1、首先,在工具箱中将ToolTip控件拖入到Winform界面下方。2、接着,在指定的ListBox添加:XXX_MouseMove事件(如已添加则忽略此步)。其中:XXX为您的控件名称。3、在该事件中添加如此......
  • Python接口测试实战
    使用Python对登录接口进行测试1.接口测试是针对软件对外提供服务得接口得输入输出进行得测试,验证接口功能与接口描述文档得一致性返回结果可以为字符串,json,xml等2.接......
  • C# .Net中鼠标Cursor的公用辅助类
    有时,我们需要将背景透明的png或gif格式图片生成的Cursor,甚至将其旋转后生成旋转效果的Cursor(可指定热点)。直接上源码:usingSystem;usingSystem.IO;usingSystem.Reflecti......
  • C# .net中B样条曲线转贝塞尔曲线
    PointF[]Spline2Bezier(PointF[]points,intstart,intnum,boolclosed,floattension)privatestaticPointF[]Spline2Bezier(PointF[]points,intstart,intnum......
  • 从.net Framework4.6WPF升级到.netcore3.1/net5/6/7.0版本
    因项目需要,需将.netFramework4.6WPF升级到.netcore3.1/net5.0/6.0/7.0版本,通过很多办法解决,开始搞得一头雾水。终于,找到了办法。1、首先下载upgrade-assistant工具(.net升级......
  • C#使用拉依达准则(3σ准则)剔除异常数据(.Net剔除一组数据中的奇异值)
    1、问题的提出:电池生产中,遇到一批电池的测量结果数据:电压值电池个数电压值电池个数电压值电池个数电压值电池个数0.0561 4.091 4.14617 4.174134340.3211 4.0941 4.147......
  • #yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-委托、匿名方法、Lambda、泛型
    前言在.NET中,委托是一种类型,它可以持有对一个或多个方法的引用,并允许将这些方法作为参数传递给其他方法。.NET中的委托类似于C和C++中的函数指针,但具有更高的类型安......
  • .NET微服务系统迁移至.NET6.0的故事
    本次迁移涉及的是公司内部一个业务子系统,该系统是一个多样化的应用,支撑着公司的多个业务方向。目前,该系统由40多个基于.NET的微服务应用构成,使用数千个CPU核心和数TB内存,......