依赖倒置原则(DIP)实践:是否需要为接口单独创建项目/DLL?
分层架构下DIP的正确实现方案
你提到的将接口迁移到双方共同引用的独立DLL的方案是完全合理的,这也是行业内落地依赖倒置原则时,解决循环依赖问题的标准实践之一。
问题根源说明
你原本的思路符合DIP的核心定义:上层(业务层)定义抽象,下层(DAL)实现抽象。但如果把接口直接定义在业务层DLL中,会出现循环依赖的本质原因是依赖方向冲突:
- 业务层原本需要依赖DAL做数据落地,所以要引用DAL
- DAL要实现业务层定义的接口,又必须引用业务层
双向引用自然就形成了死循环。
推荐的两种落地实现
方案1:独立抽象层方案(也就是你提到的方案,适合中大型项目)
你可以新增一个纯契约类的独立DLL项目,比如命名为[你的项目名].Contracts或[你的项目名].Abstractions,调整后的依赖关系如下:
- 独立抽象层:不依赖任何其他业务、DAL项目,只存放业务层需要的抽象接口,比如
IUserRepository、IOrderRepository等数据访问抽象 - 业务层:仅引用该独立抽象层,所有数据操作都依赖抽象层的接口,不直接引用DAL的具体实现
- DAL层:仅引用该独立抽象层,实现抽象层中定义的对应数据访问接口即可
这种方案完全符合DIP要求:高层模块、低层模块都依赖抽象,同时完全规避了循环依赖问题,后续如果要替换DAL的实现(比如从SQLServer改成MongoDB),只需要新增实现类即可,不需要修改业务层和抽象层的代码。
方案2:调整引用方向(适合小型项目,不想多维护独立DLL的场景)
如果项目规模很小,不想新增额外的项目,也可以直接调整引用关系:
- 去掉业务层对DAL的直接引用
- 接口直接定义在业务层内部,DAL层引用业务层实现对应接口
- 由最上层的入口项目(比如API、Web应用项目)同时引用业务层和DAL,通过依赖注入容器将DAL的实现注入到业务层的接口中
这种方案同样符合DIP规则,也不会产生循环依赖,只是抽象和业务层耦合在一起,扩展性比独立抽象层方案差一些。
内容的提问来源于stack exchange,提问作者firendlyQuestion
相关产品推荐
相关产品推荐

