Eventos de persistência e domínio com objetos ignorantes de persistência

Eu estudei sobre design orientado a domínio em conjunto comeventos de domínio. Eu realmente gosto das separações de preocupações que esses eventos fornecem. Corri um problema com a ordem de persistir um objeto de domínio e gerar eventos de domínio. Gostaria de gerar eventos nos objetos de domínio, mas quero que eles sejam persistentes e ignorantes.

Eu criei um básicoShoppingCartService, com issoCheckout método:

public void Checkout(IEnumerable<ShoppingCartItem> cart, Customer customer)
{
    var order = new Order(cart, customer);

    _orderRepositorty.Add(order);
    _unitOfWork.Commit();
}

Neste exemplo, o construtor deOrder&nbsp;levantaria umOrderCreated&nbsp;evento que pode ser tratado por determinados manipuladores. No entanto, não quero que esses eventos sejam gerados quando a entidade ainda não persistiu ou quando a persistência de alguma forma falha.

Para resolver esse problema, imaginei várias soluções:

1. Crie eventos no serviço:

Em vez de aumentar o evento no objeto de domínio, eu poderia gerar eventos no serviço. Nesse caso, oCheckout&nbsp;método aumentaria aOrderCreated&nbsp;evento. Uma das desvantagens dessa abordagem é que, olhando oOrder&nbsp;objeto de domínio, não está claro quais eventos são gerados por quais métodos. Além disso, um desenvolvedor deve se lembrar de aumentar o evento quando um pedido for criado em outro lugar. Não parece certo.

2. Eventos do domínio na fila

Outra opção é enfileirar eventos de domínio e aumentá-los quando a persistência for bem-sucedida. Isso poderia ser alcançado por umusing&nbsp;instrução por exemplo:

using (DomainEvents.QueueEvents<OrderCreated>())
{
    var order = new Order(cart, customer);

    _orderRepositorty.Add(order);
    _unitOfWork.Commit();
}

oQueueEvents<T>&nbsp;O método definiria um booleano paratrue&nbsp;e aDomainEvents.Raise<T>&nbsp;O método enfileiraria o evento em vez de executá-lo diretamente. No descarte de retorno de chamada deQueueEvent<T>, os eventos na fila são executados, o que garante que a persistência já aconteceu. Isso parece bastante complicado e exigia que o serviço soubesse qual evento está sendo gerado no objeto de domínio. No exemplo que forneci, ele também suporta apenas um tipo de evento a ser gerado, no entanto, isso pode ser contornado.

3. Persistir no evento do domínio

Eu poderia persistir o objeto usando um evento de domínio. Isso parece bom, exceto pelo fato de que o manipulador de eventos que persiste no objeto deve ser executado primeiro, no entanto, li em algum lugar que os eventos do domínio não devem depender de uma ordem específica de execução. Talvez isso não seja importante e os eventos de domínio possam, de alguma forma, saber em qual ordem os manipuladores devem executar. Por exemplo: suponha que eu tenha uma interface definindo um evento de domíniomanipulador, uma implementação seria assim:

public class NotifyCustomer : IDomainEventHandler<OrderCreated>
{
   public void Handle(OrderCreated args)
   {
       // ...
   }
}

Quando eu quero lidar com a persistência no uso de um manipulador de eventos também, eu criaria outro manipulador, derivado da mesma interface:

public class PersistOrder : IDomainEventHandler<OrderCreated>
    {
       public void Handle(OrderCreated args)
       {
           // ...
       }
    }
}

AgoraNotifyCustomer&nbsp;o comportamento depende da ordem que está sendo salva no banco de dados, portanto, oPersistOrder&nbsp;O manipulador de eventos deve ser executado primeiro. É aceitável que esses manipuladores introduzam uma propriedade, por exemplo, que indique a ordem de sua execução? Um piscar de olhos com a implementação doDomainEvents.Raise<OrderCreated>()&nbsp;método:

foreach (var handler in Container.ResolveAll<IDomainEventHandler<OrderCreated>>().OrderBy(h => h.Order))
{
    handler.Handle(args);
}

Agora, minha pergunta é: tenho outras opções? Estou esquecendo de algo? E o que você acha das soluções que propus?