前言
在软件的实际开发中,一个软件通常由多个项目组成,这些项目都会直接或者间接被主 ASP.NET Core 项目引用。
这些项目中通常都会用到若干个被注入的服务,因此我们需要在主 ASP.NET Core 项目的 Program.cs 中注册这些服务。这样不仅会增加了 Program.cs 管理的复杂度,而且也增加了项目的耦合度。
如果能让各个项目负责各自的服务注册,就能够减小项目之间的耦合度。
Step By Step 步骤
- 创建类库项目 "SampleService”
- 创建接口IMyService
namespace SampleService { public interface IMyService { void SayHello(); } }
3.创建类库项目 "SampleServiceImpl1” ,并引用 "SampleService” 项目
4.创建 IMyService 的实现类 CnService
using SampleService; namespace SampleServiceImpl1 { public class CnService : IMyService { public void SayHello() { Console.WriteLine("你好"); } } }
5.引用 Nuget 包 Zack.Commons
6.创建Zack.Commons中的 IModuleInitializer 接口的实现类 ModuleInitializer
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 步骤,注意不同的代码:
- IMyService 的实现类 EnService
using SampleService; namespace SampleServiceImpl2 { public class EnService : IMyService { public void SayHello() { Console.WriteLine("Hello"); } } }
- IModuleInitializer 接口的实现类 ModuleInitializer
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,编写服务注册和使用代码(重点看注释)
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 类完成的。
这样,我们就减小了项目之间的耦合度,实现了程序集的 "服务注册自治”