服务注册自治,降低 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 类完成的。

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

相关推荐
code bean1 小时前
【C#】 `Channel<T>` 深度解析:生产者-消费者模式的现代解法
数据结构·c#
维克兜率天1 小时前
【维克】大数定律与中心极限定理:为什么长期均值终将回归?
经验分享·学习·金融·概率论
吴可可1235 小时前
C# CAD二次开发:合并首尾重合多段线
c#
个 人 练 习 生5 小时前
strcmp与strstr函数的模拟实现
c语言·开发语言·经验分享·学习·程序人生
EIP低代码平台6 小时前
EIP低代码平台 - 应用管理 - 表单设计
低代码·c#·权限·工作流·netcore
czhc11400756636 小时前
726:zoffset
c#
ez在线工具网7 小时前
从零部署开源流媒体下载工具 FlowPick:Nuxt 4 项目本地跑起来 + 二次开发实战
经验分享·开源软件
一个人旅程~7 小时前
房子重新被定义为大宗耐用消费品
经验分享·其他·新浪微博
向夏威夷 梦断明暄9 小时前
C# 弃元模式:从语法糖到性能利器的深度解析
服务器·数据库·c#
天竺鼠不该去劝架9 小时前
openclaw安全预警之后:金融级智能体该怎么上
经验分享