ApplicationLayer与DomainLayer解耦:仅引用Domain.Contract如何创建ICard实例
解决方案
方案1:工厂接口分离+依赖注入(推荐)
该方案完全符合你当前的项目引用规则,不会产生循环依赖,也不需要Application层直接引用Domain层:
1. 在Domain.Contract项目中定义工厂接口
把工厂的抽象契约放到公共契约层,Application层只需要依赖这个接口就能完成实例创建:
public interface ICardFactory { // 方法参数根据Card构造需要的业务参数定义 ICard CreateCard(string cardNumber, DateTime expireTime); }
2. 在Domain项目中实现工厂接口
工厂实现放在Domain层,可以直接访问Card实现类,封装聚合根的构造逻辑:
public class CardFactory : ICardFactory { public ICard CreateCard(string cardNumber, DateTime expireTime) { // 可以在这里加构造前的业务校验 return new Card(cardNumber, expireTime); } }
3. Application层注入工厂接口使用
CommandHandler只依赖Domain.Contract中的接口,不需要感知具体实现:
public class CardCommandHandler { private readonly ICardFactory _cardFactory; private readonly ICardRepository _repository; // 构造函数注入依赖,由DI容器自动注入实现 public CardCommandHandler(ICardFactory cardFactory, ICardRepository repository) { _cardFactory = cardFactory; _repository = repository; } public void CommandHandlerMethod() { // 传入构造Card需要的业务参数完成实例创建 var card = _cardFactory.CreateCard("1234-5678", new DateTime(2030,12,31)); _repository.Save(card); } }
4. 组合根注册依赖
你的程序启动项目(比如ASP.NET Core的Web入口项目)作为组合根,是唯一可以引用所有下层项目的上层节点,只需要在启动注册逻辑中添加如下配置即可:
// 以ASP.NET Core为例,在Program.cs中注册 builder.Services.AddScoped<ICardFactory, CardFactory>();
方案2:直接注册ICard实现(适合简单构造场景)
如果Card的构造逻辑非常简单,没有复杂的业务校验和参数处理,可以直接在组合根注册ICard的实现:
builder.Services.AddTransient<ICard, Card>();
需要创建实例时,在Application层注入IServiceProvider直接解析即可,不过该方案无法封装聚合根的构造规则,不适合复杂的领域模型场景。
两种方案都不会破坏你现有的分层引用规则:Domain和Application都仅依赖Domain.Contract,没有循环引用,也完全符合面向接口编程的要求。
内容的提问来源于stack exchange,提问作者Arman Rasouli
相关产品推荐
相关产品推荐

