ASP.NET 9.0中无需跨项目引用配置Api服务实现的方法
解决方案:模块主动注册 + 启动层触发加载
基于你的整洁架构约束,我们可以通过模块主动注册到基础工厂+启动层间接触发程序集加载的方式,实现无项目引用、无反射的服务配置:
1. 完善Base项目的模块契约与工厂
保留你原有的ModuleFactory,去掉无法访问非共享项目的LoadModules方法,专注于模块存储与服务注册:
// Base项目(无任何外部引用) public interface IModuleBase { void ConfigureServices(IServiceCollection services); } public static class ModuleFactory { private static readonly List<IModuleBase> Modules = []; public static void RegisterModules(IServiceCollection services) { foreach (var module in Modules) { module.ConfigureServices(services); } } public static void AddModule(IModuleBase module) { if (!Modules.Contains(module)) { Modules.Add(module); } } }
2. 非共享项目模块主动注册
在每个非共享项目(如Application、Infrastructure)中,实现IModuleBase并通过静态构造函数主动将自身注册到Base的工厂中——静态构造函数会在类首次被访问时自动执行:
// Application项目(仅引用Base项目) public class ApplicationModule : IModuleBase { static ApplicationModule() { // 主动向Base工厂注册当前模块 ModuleFactory.AddModule(new ApplicationModule()); } public void ConfigureServices(IServiceCollection services) { // 注册当前模块的业务服务 services.AddScoped<IUserAppService, UserAppService>(); // ...其他服务注册逻辑 } }
3. Api项目触发模块加载
利用Api可访问的共享项目作为桥接,通过标记类型触发非共享项目的程序集加载:
第一步:共享项目定义标记接口
// 共享项目(Api可访问,非共享项目可引用) public interface IModuleMarker { }
第二步:非共享模块实现标记接口
// Application项目 public class ApplicationModule : IModuleBase, IModuleMarker { // 静态构造函数逻辑同上 }
第三步:Api启动时触发加载
在Api的Program.cs中,仅需引用标记接口类型,即可触发包含该接口实现的非共享程序集加载,进而触发模块的静态构造函数完成注册:
// Api项目(启动项,引用Base项目与共享项目) var builder = WebApplication.CreateBuilder(args); // 触发非共享程序集加载,自动执行模块的静态构造函数完成注册 _ = typeof(IModuleMarker); // 调用Base工厂完成所有模块的服务注册 ModuleFactory.RegisterModules(builder.Services); // 后续Web应用配置... var app = builder.Build(); app.Run();
核心逻辑说明
- 完全避免了Base项目对非共享项目的引用,也无需Api直接引用非共享项目,仅依赖共享项目作为桥接
- 无反射操作,所有模块注册通过静态构造函数自动触发
- 静态构造函数的执行时机由CLR保证,确保模块在服务注册前已完成向工厂的注册
内容的提问来源于stack exchange,提问作者Ahmad
相关产品推荐
相关产品推荐

