整洁架构(Clean Architecture)中Api层为何直接引用数据库层?如何优化?
整洁架构下依赖注入的优化方案
问题本质
教程中直接在API层写服务注册的写法属于简化演示的实现,仅用于快速跑通功能,没有遵循整洁架构的分层约束:核心层存放抽象、外层存放实现,外层依赖内层,内层不感知外层的具体实现。直接在API层声明DatabaseService的注册逻辑,会让API层不必要地感知具体实现类,违反依赖倒置原则。
标准优化实现
不需要额外新增核心层承载DI逻辑,采用「实现模块自托管注册」的方案即可解决问题,落地步骤如下:
- 调整抽象的存放位置:将
IDatabaseService接口移动到核心层(Core/Application层,存放业务抽象、领域规则),Database项目仅保留DatabaseService实现类、DbContext等数据库相关代码,Database项目引用核心层,而非核心层依赖实现。 - 在Database项目中封装注册扩展方法,将所有数据库相关的服务注册逻辑内聚到实现模块内部,示例代码:
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Configuration; namespace YourProject.Database; public static class DatabaseServiceRegistration { public static IServiceCollection AddDatabaseServices(this IServiceCollection services, IConfiguration configuration) { // 所有数据库相关的注册逻辑都封装在此处 services.AddDbContext<IDatabaseService, DatabaseService>(options => { options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")); }); return services; } }
- API层仅需调用封装好的扩展方法即可,不需要感知任何具体实现类:
// Program.cs 中仅需要这一行代码完成数据库服务注册 builder.Services.AddDatabaseServices(builder.Configuration);
该方案下,API层不需要直接操作DatabaseService实现类,后续如果需要替换数据库实现(比如从EF Core切换到Dapper),只需要修改AddDatabaseServices的内部逻辑,或者替换为新实现模块的扩展方法即可,API层的代码不需要做任何调整,完全符合整洁架构的分层要求。
关于新增DI管理层的疑问解答
- 不建议将DI注册逻辑放到核心层:核心层的定位是存放纯业务逻辑,不能和特定框架(比如Asp.Net Core的DI组件)耦合,否则会破坏核心层的可移植性,比如后续要做桌面端适配时,核心层带了Asp.Net Core的依赖会完全无法复用。
- 如果是中大型项目,模块数量极多,可以单独建一个公共的依赖注入项目,统一引用所有实现模块,把所有服务注册的扩展方法集中到这个项目管理,API层仅需要引用这个DI项目即可,中小项目没必要做这个额外拆分,直接把注册逻辑放到对应实现模块即可。
内容的提问来源于stack exchange,提问作者gharel
相关产品推荐
相关产品推荐

