经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » ASP.net » 查看文章
.NET依赖注入之一个接口多个实现
来源:cnblogs  作者:几秋  时间:2023/2/27 9:44:41  对本文有异议

前言

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

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

  1. public interface ICustomService
  2. {
  3. void MethodA();
  4. void MethodB();
  5. }
  6. public class CustomService: ICustomService
  7. {
  8. public void MethodA()
  9. {
  10. }
  11. public void MethodB()
  12. {
  13. }
  14. }
  15. //注入
  16. builder.Services.AddTransient<ICustomService, CustomService>();
  17. //使用
  18. private readonly ICustomService _customService;
  19. public CustomController(ICustomService customService)
  20. {
  21. _customService = customService;
  22. }

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

使用多个接口实现

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

  1. //基接口
  2. public interface ICustomBaseService
  3. {
  4. void MethodA();
  5. void MethodB();
  6. }
  7. //多个空接口
  8. public interface ICustomService : ICustomBaseService
  9. {
  10. }
  11. public interface ICustomServiceV2 : ICustomBaseService
  12. {
  13. }
  14. //第一种实现
  15. public class CustomService: ICustomService
  16. {
  17. public void MethodA()
  18. {
  19. }
  20. public void MethodB()
  21. {
  22. }
  23. }
  24. //第二种实现
  25. public class CustomServiceV2: ICustomServiceV2
  26. {
  27. public void MethodA()
  28. {
  29. }
  30. public void MethodB()
  31. {
  32. }
  33. }
  34. //注入
  35. builder.Services.AddTransient<ICustomService, CustomService>();
  36. builder.Services.AddTransient<ICustomServiceV2, CustomServiceV2>();
  37. //使用
  38. private readonly ICustomService _customService;
  39. private readonly ICustomServiceV2 _customServiceV2;
  40. public CustomController(ICustomService customService,ICustomServiceV2 customServiceV2)
  41. {
  42. _customService = customService;
  43. _customServiceV2 = customServiceV2;
  44. }

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

使用单接口实现

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

  1. public interface ICustomService
  2. {
  3. void MethodA();
  4. void MethodB();
  5. }
  6. //第一种实现
  7. public class CustomService: ICustomService
  8. {
  9. public void MethodA()
  10. {
  11. }
  12. public void MethodB()
  13. {
  14. }
  15. }
  16. //第二种实现
  17. public class CustomServiceV2: ICustomService
  18. {
  19. public void MethodA()
  20. {
  21. }
  22. public void MethodB()
  23. {
  24. }
  25. }
  26. //注入
  27. builder.Services.AddTransient<ICustomService, CustomService>();
  28. builder.Services.AddTransient<ICustomService, CustomServiceV2>();
  29. //使用
  30. private readonly ICustomService _customService;
  31. private readonly ICustomService _customServiceV2;
  32. public CustomController(IEnumerable<ICustomService> customServices)
  33. {
  34. _customService = customServices.ElementAt(0);
  35. _customServiceV2 = customServices.ElementAt(1);
  36. }

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

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

答案在Microsoft.Extensions.DependencyInjection.ServiceDescriptorMicrosoft.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

原文链接:https://www.cnblogs.com/netry/p/net-dependency-injection-multiple-implementations.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号