为 CQRS 实施包装 Masstransit 是一个好习惯吗?

Is it a good practice to wrap Masstransit for CQRS implementation?

我宁愿有一个单独的 CommandBusEventBus 以及 ICommandHandler<TCommand>IEventHandler<TCommand> 这样 OrderEventHandler class 看起来像:

public class OrderEventHandler :
    IEventHandler<OrderPlaced>,
    IEventHandler<OrderRegistrantAssigned>,
    IEventHandler<OrderTotalsCalculated>,
    IEventHandler<OrderConfirmed>,
    IEventHandler<OrderExpired>,
    IEventHandler<SeatAssignmentsCreated>,
    IEventHandler<SeatAssigned>,
    IEventHandler<SeatAssignmentUpdated>,
    IEventHandler<SeatUnassigned>
{ 
    public void Handle(OrderPlaced @event){...}
    .
    .
    .
}

一个可能的解决方案是在 Masstransit 基础设施和我的 CQRS 之间提供一个采用者(比如 ConsumerToHandlerAdopter<T> 它只公开我通常需要的上下文细节)。

但是由于我是 Masstransit 的新手,我无法理解以后可能需要处理的问题。

所以我的问题是: 通常是否值得包装 Masstransit 以便我处理自己的基础设施?

我们使用 MassTransit 广泛实施 CRQS,但仅用于命令处理。

多次讨论了不使用消息传递基础结构来同步写入和读取模型的原因。主要原因是您有机会坚持更改而不发布事件,因为这是基础架构的两个不同部分。除非你使用DTC之类的东西,否则你将无法保证模型之间的一致性。

此外,在这一点上,我们也希望远离 "God handler" classes。 MassTransit 特别擅长通过将每个消费者分离到单独的 class.

来执行 SRP(单一责任原则)

对于一般领域基于事件的集成(反应式事件处理),我们也使用 MassTransit。

你也可以有实现多个消息接口的事件,这样你会有更全面的事件处理:

public interface CustomerRegistered
{
    string FullName { get; }
}

public interface OrderPlaced
{
    string Reference { get; }
    List<OrderLine> Lines { get; }
}

public class NewCustomerOrderedStuff : CustomerRegistered, OrderPlaced
{
...
}

public class CustomerRegisteredConsumer : IConsumer<CustomerRegistered>

public class OrderPlacedConsumer : IConsumer<OrderPlaced>

每个消费者都有不同的关注点,可以生活在一个单独的有界上下文(服务)中。