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

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

相关推荐
浅念-6 分钟前
C语言——内存函数
c语言·经验分享·笔记·学习·算法
asdzx671 小时前
使用 Python 轻松添加文本水印到 PDF
经验分享
LaughingZhu2 小时前
Product Hunt 每日热榜 | 2026-01-28
数据库·经验分享·神经网络·搜索引擎·chatgpt
晚霞的不甘2 小时前
Flutter for OpenHarmony《智慧字典》 App 底部导航栏深度解析:构建多页面应用的核心骨架
前端·经验分享·flutter·ui·前端框架·知识图谱
PfCoder2 小时前
C# 中的定时器 System.Threading.Timer用法
开发语言·c#
缺点内向2 小时前
Word 自动化处理:如何用 C# 让指定段落“隐身”?
开发语言·c#·自动化·word·.net
KvPiter2 小时前
Clawdbot 中文汉化版 接入微信、飞书
人工智能·c#
WZgold1413 小时前
黄金突破5200美元!去美元化浪潮中的价值锚点重构
经验分享·重构
asyxchenchong8883 小时前
R语言生物群落数据分析——涵盖数据清洗、多元统计分析、混合效应模型、随机森林及结构方程模型等
经验分享
曹牧3 小时前
C#:重载窗体构造函数
开发语言·c#