基于Clean Architecture与Mediator模式的Mass Transit逻辑位置咨询
业务逻辑该放在Consumers还是Application层Handlers?
核心原则要先明确:Clean Architecture的核心是依赖倒置,核心业务逻辑必须放在内层(Application/Domain),而Consumers属于消息适配层,只做消息的接收与转发,不承载核心业务逻辑。
下面结合你的项目结构给出具体建议:
1. 优先将业务逻辑放在Application层的Handlers里
Application层本身就是处理业务用例的核心层,不管触发逻辑的是WebApi的请求,还是消息队列的事件,核心业务逻辑都应该复用同一份实现。这样做的好处:
- 避免重复代码:比如创建订单的逻辑,不管是用户通过API提交,还是系统通过消息触发,都调用同一个Handler,不用写两遍业务逻辑。
- 便于测试:测试业务逻辑时不需要依赖消息队列,直接调用Handler即可,降低测试复杂度。
- 符合分层原则:Application层不依赖任何外部基础设施(包括消息队列),保持业务逻辑的纯净性和可移植性。
2. Consumers仅做适配性工作
Consumers里只放和消息消费强相关的适配逻辑,比如:
- 消息参数的格式转换(把消息DTO转换成Application层的Command/Query)
- 消息消费的基础校验(比如必填字段是否存在,格式是否合法,而非业务规则校验)
- 消息重试、死信的基础处理(比如记录消费日志)
3. 结合你的项目结构的具体实现示例
SharedContracts项目
存放公共的消息契约(如CreateOrderMessage),保证WebApi、Messaging等项目引用的消息格式一致。
Messaging项目
定义Mass Transit的Consumer,作为薄适配层:
public class CreateOrderConsumer : IConsumer<CreateOrderMessage> { private readonly IMediator _mediator; public CreateOrderConsumer(IMediator mediator) { _mediator = mediator; } public async Task Consume(ConsumeContext<CreateOrderMessage> context) { // 仅做参数转换,不处理业务 var command = new CreateOrderCommand( context.Message.OrderId, context.Message.CustomerId, context.Message.Items); // 转发到Application层处理核心逻辑 await _mediator.Send(command); } }
Application层
实现核心业务逻辑的Handler:
public class CreateOrderHandler : IRequestHandler<CreateOrderCommand, Result> { private readonly IOrderRepository _orderRepository; private readonly ICustomerRepository _customerRepository; public CreateOrderHandler(IOrderRepository orderRepository, ICustomerRepository customerRepository) { _orderRepository = orderRepository; _customerRepository = customerRepository; } public async Task<Result> Handle(CreateOrderCommand request, CancellationToken cancellationToken) { // 核心业务逻辑:校验客户合法性、创建订单实体、持久化等 var customer = await _customerRepository.GetByIdAsync(request.CustomerId); if (customer == null) return Result.Failure("客户不存在"); var order = Order.Create(request.OrderId, customer.Id, request.Items); await _orderRepository.AddAsync(order); return Result.Success(); } }
总结
核心业务逻辑必须放在Application层的Handlers里,Consumers只负责把消息转换为Application层能处理的命令/查询,这样既符合Clean Architecture的分层规范,又能保证业务逻辑的复用性、可测试性和可维护性。
内容的提问来源于stack exchange,提问作者pietro
相关产品推荐
相关产品推荐

