Есть ли какой-нибудь способ сохранить контекст событий домена незнакомым с NServiceBus 6 и удалением IBus?
Я сталкиваюсь с ситуацией, когда в настоящее время мы используем интерфейс IBus (NServiceBus v5) в обработчиках событий домена для отправки команд в бэкэнд-сервис для обработки. С IBus эти команды могут быть отправлены независимо от того, что вызвало событие, будь то при получении запроса Web API или в качестве части обработчика NServiceBus (модель общего домена). Но в NServiceBus v6 с переходом к контекстно-зависимым интерфейсам, IEndpointInstance или IMessageHandlerContext, кажется, что мои обработчики событий домена теперь должны стать осведомленными о контексте. И, кроме того, похоже, что IMessageHandlerContext доступен только через внедрение метода, поэтому мне может потребоваться разбросать этот параметр по всему стеку вызовов?
Есть ли какой-то подход, который я не вижу, с помощью которого я могу не знать контекст обработчиков событий моего домена? Или я следовал какой-то плохой практике, которая раскрывается через этот запах кода?
РЕДАКТИРОВАТЬ
Вот попытка свести сценарий к наиболее значимым частям. В модели домена есть порядок, статус которого может измениться. Когда статус заказа меняется, мы запускаем событие домена StatusChanged через издателя. Подписчик на это конкретное событие домена записывает запись об изменении статуса, а также отправляет команду NServiceBus для передачи этого статуса - обработчик для этой конкретной команды будет следовать некоторой дополнительной логике в отношении того, отправлять ли электронные письма, SMS-сообщения и т. Д.., детали которого я не думаю, имеют отношение.
Заказать доменный объект
public class Order
{
private OrderStatusCode _statusCode;
public OrderStatusCode StatusCode
{
get { return _statusCode; }
private set { _statusCode = value; }
}
public void ChangeStatus(OrderStatusCode status)
{
Status = status;
Publish(new StatusChanged(CreateOrderSnapshot(), status));
}
protected void Publish<T>(T @event) where T : IDomainEvent
{
DomainEventPublisher.Instance.Publish(@event);
}
}
Издатель событий домена
public class DomainEventPublisher : IDomainEventPublisher
{
private static IDomainEventPublisher _instance;
public static IDomainEventPublisher Instance
{
get { return _instance ?? (_instance = new DomainEventPublisher()); }
}
public ISubscriptionService SubscriptionService { get; set; }
public void Publish<T>(T @event) where T : IDomainEvent
{
if (SubscriptionService == null) return;
var subscriptions = SubscriptionService.GetSubscriptions<T>();
subscriptions.ToList().ForEach(x => PublishToConsumer(x, @event).GetAwaiter().GetResult());
}
private static async Task PublishToConsumer<T>(IEventSubscriber<T> x, T eventMessage) where T : IDomainEvent
{
await x.HandleEvent(eventMessage);
}
}
Обработчик событий домена изменен статус
public class StatusChangedHandler : IEventSubscriber<StatusChanged>
{
private readonly IBus _bus;
private readonly IOrdersRepository _ordersRepository;
public StatusChangedHandler(IBus bus, IOrdersRepository ordersRepository)
{
_bus = bus;
_ordersRepository = ordersRepository;
}
public async Task HandleEvent(StatusChanged @event)
{
var statusTrailEntry = new OrderStatusTrailEntry(@event.OrderSnapshot, @event.Status);
var txOptions = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted };
using (
var scope = new TransactionScope(TransactionScopeOption.Required, txOptions))
{
await _ordersRepository.SaveStatusTrail(statusTrailEntry);
if (communicateStatus)
{
_bus.Send(new SendCommunicationCommand(@event.OrderSnapshot, @event.Status));
}
scope.Complete();
}
}
}
Дело в том, что до сих пор ни одному из приведенного выше примера кода не требовалось знать, изменилось ли состояние в результате запроса, поступающего через запрос Web API, или в результате изменения состояния в контексте сообщения NServiceBus. обработчик (внутри службы Windows) - интерфейс IBus не зависит от контекста. Но с различием между IEndpointInstance и IMessageHandlerContext в NServiceBus v6 я не чувствую, что у меня такая же гибкость.
Если я правильно понимаю, я могу зарегистрировать IEndpointInstance в своем контейнере и внедрить его в EventSubscriber, так что я буду покрыт в случае вызова веб-API, но мне также потребуется добавить IMessageHandlerContext в качестве параметра опционально передаваться через стек вызовов из ChangeStatus в Publisher и, наконец, в подписчик событий домена, если происходит изменение состояния в контексте обработчика сообщений. На самом деле не хочется добавлять этот параметр по всему стеку вызовов.