服务注册自治,降低 ASP.NET Core Web API 依赖注入的耦合度和复杂度

前言

在软件的实际开发中,一个软件通常由多个项目组成,这些项目都会直接或者间接被主 ASP.NET Core 项目引用。

这些项目中通常都会用到若干个被注入的服务,因此我们需要在主 ASP.NET Core 项目的 Program.cs 中注册这些服务。这样不仅会增加了 Program.cs 管理的复杂度,而且也增加了项目的耦合度。

如果能让各个项目负责各自的服务注册,就能够减小项目之间的耦合度。

Step By Step 步骤

  1. 创建类库项目 "SampleService"

  2. 创建接口IMyService

    c# 复制代码
    namespace SampleService
    {
    	public interface IMyService
    	{
    		void SayHello();
    	}
    }
  3. 创建类库项目 "SampleServiceImpl1" ,并引用 "SampleService" 项目

  4. 创建 IMyService 的实现类 CnService

    c# 复制代码
    using SampleService;
    
    namespace SampleServiceImpl1
    {
    	public class CnService : IMyService
    	{
    		public void SayHello()
    		{
    			Console.WriteLine("你好");
    		}
    	}
    }
  5. 引用 Nuget 包 Zack.Commons

  6. 创建Zack.Commons中的 IModuleInitializer 接口的实现类 ModuleInitializer

    c# 复制代码
    using Microsoft.Extensions.DependencyInjection;
    using Zack.Commons;
    using SampleServiceImpl1;
    using SampleService;
    
    class ModuleInitializer : IModuleInitializer
    {
    	public void Initialize(IServiceCollection services)
    	{
    		// 把 CnService 注册为 IMyService 的实现服务
    		services.AddScoped<IMyService, CnService>();
    	}
    }
  7. 创建类库项目 "SampleServiceImpl2" ,重复 3~6 步骤,注意不同的代码:

    1. IMyService 的实现类 EnService

      c# 复制代码
      using SampleService;
      
      namespace SampleServiceImpl2
      {
      	public class EnService : IMyService
      	{
      		public void SayHello()
      		{
      			Console.WriteLine("Hello");
      		}
      	}
      }
    2. IModuleInitializer 接口的实现类 ModuleInitializer

      c# 复制代码
      using Microsoft.Extensions.DependencyInjection;
      using Zack.Commons;
      using SampleServiceImpl2;
      using SampleService;
      
      class ModuleInitializer : IModuleInitializer
      {
      	public void Initialize(IServiceCollection services)
      	{
      		// 把 EnService 注册为 IMyService 的实现服务
      		services.AddScoped<IMyService, EnService>();
      	}
      }
  8. 创建控制台项目 "MainProject"

  9. 引用 "SampleService" , "SampleServiceImpl1" , "SampleServiceImpl2" 这三个项目

  10. 引用 Nuget 包 Microsoft.Extensions.DependencyInjection

  11. 打开 Program.cs,编写服务注册和使用代码(重点看注释

    c# 复制代码
    using Microsoft.Extensions.DependencyInjection;
    using SampleService;
    using Zack.Commons;
    
    // 1.创建服务注册容器
    ServiceCollection services=new ServiceCollection();
    
    // 2.调用 GetAllReferencedAssemblies 方法获取所有的用户程序集
    var assemblies = ReflectionHelper.GetAllReferencedAssemblies();
    
    // 3.调用 RunModuleInitializers 方法扫描指定程序集中所有实现了 IModuleInitializer 接口的类
    //   并且调用它们的Initialize方法来完成服务的注册
    services.RunModuleInitializers(assemblies);
    
    // 4.使用
    using var sp = services.BuildServiceProvider();
    
    var items = sp.GetServices<IMyService>();
    foreach (var item in items)
    {
    	item?.SayHello();
    }

总结

控制台项目 "MainProject" 只是添加了对 "SampleServiceImpl1" 和 "SampleServiceImpl2" 的引用,

但是在项目 "MainProject" 中并没有使用代码注册 CnService 服务和 EnService 服务,服务的注册工作是由 "SampleServiceImpl1" 中的 ModuleInitializer 类完成的。

这样,我们就减小了项目之间的耦合度,实现了程序集的 "服务注册自治"

相关推荐
牛哇网络工作室1 小时前
UnityHDRP写实数字人全流程基础5—语音输入和语音识别
android·unity·c#·游戏引擎·aigc·语音识别·xcode
2501_926978333 小时前
AGI 的四种瓶颈:资源型还是发现型--以及DSH的位置
人工智能·经验分享·笔记·ai写作
LuminousCPP9 小时前
栈和队列专题(一):LeetCode 20. 有效的括号
数据结构·经验分享·笔记·leetcode·手写栈
上海广测检测科技有限公司11 小时前
投影仪ETL认证技术解读:光源安全评估与测试框架
经验分享
zlinear数据采集卡11 小时前
数据采集卡从入门到精通(9):分辨率与精度——16位卡不等于1/65536的精度
开发语言·数据库·fpga开发·开源·c#
薰珞婷紫小亭子13 小时前
如何解决IEEE期刊LaTeX 模版编译pdf出现大空白的问题
经验分享·pdf
深澈Vincel14 小时前
我用 C# + WebView2 做了一个针对“流氓软件”的“一键清理工具“:架构实践与踩坑记录
c#
zlinear数据采集卡15 小时前
数据采集卡从入门到精通(7):流水线型ADC——级级接力,高速与高精的平衡术
开发语言·arm开发·嵌入式硬件·fpga开发·c#
kingwebo'sZone16 小时前
C# 根据公式计算的方法
开发语言·c#
阿部多瑞 ABU16 小时前
告别手工核图:基于 .NET + MuPDFCore 的 CAD 等轴测 PDF 材料表提取与新旧版本对比实战
后端·算法·ui·pdf·c#