-
-
Save vkhorikov/ee12c0982bf177db155c12621cafc58d to your computer and use it in GitHub Desktop.
Merging domain events
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public sealed class Messages | |
{ | |
private readonly IServiceProvider _provider; | |
public Messages(IServiceProvider provider) | |
{ | |
_provider = provider; | |
} | |
public void Dispatch(IDomainEvent domainEvent) | |
{ | |
Type type = typeof(IDomainEventHandler<>); | |
Type[] typeArgs = { domainEvent.GetType() }; | |
Type handlerType = type.MakeGenericType(typeArgs); | |
dynamic handler = _provider.GetService(handlerType); | |
handler.Handle((dynamic)domainEvent); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Order | |
{ | |
public void Cancel() | |
{ | |
/* ... */ | |
AddDomainEvent(new OrderCanceledEvent(Id)); | |
} | |
} | |
public class OrderCanceledEvent : IDomainEvent | |
{ | |
public int OrderId { get; } | |
public OrderCanceledEvent(int orderId) | |
{ | |
OrderId = orderId; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class OrderCanceledEventHandler : IDomainEventHandler<OrderCanceledEvent> | |
{ | |
private readonly MessageBusGateway _gateway; | |
public OrderCanceledEventHandler(MessageBusGateway gateway) | |
{ | |
_gateway = gateway; | |
} | |
public void Handle(OrderCanceledEvent domainEvent) | |
{ | |
_gateway.SendOrderCanceledMessage(domainEvent.OrderId); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Customer | |
{ | |
public void Deactivate() | |
{ | |
foreach (Order order in Orders) | |
{ | |
order.Cancel(); | |
} | |
AddDomainEvent(new CustomerDeactivatedEvent(Id)); | |
} | |
} | |
public class CustomerDeactivatedEventHandler : IDomainEventHandler<CustomerDeactivatedEvent> | |
{ | |
public void Handle(CustomerDeactivatedEvent domainEvent) | |
{ | |
_gateway.SendCustomerDeactivatedMessage(domainEvent.CustomerId); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Order | |
{ | |
public void Cancel(bool generateEvent) | |
{ | |
/* ... */ | |
if (generateEvent) | |
{ | |
AddDomainEvent(new OrderCanceledEvent(Id)); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class DomainEvent | |
{ | |
protected virtual Type SupersetFor => null; | |
public bool IsSupersetFor(DomainEvent domainEvent) | |
{ | |
return domainEvent.GetType() == SupersetFor; | |
} | |
} | |
public class CustomerDeactivatedEvent : DomainEvent | |
{ | |
protected override Type SupersetFor => typeof(OrderCanceledEvent); | |
} | |
public abstract class AggregateRoot | |
{ | |
private readonly List<DomainEvent> _domainEvents = new List<DomainEvent>(); | |
public IReadOnlyList<DomainEvent> DomainEvents => _domainEvents; | |
protected virtual void AddDomainEvent(DomainEvent newEvent) | |
{ | |
if (_domainEvents.Any(existing => existing.IsSupersetFor(newEvent))) | |
return; | |
_domainEvents.Add(newEvent); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
internal class EventDispatcher : | |
IPostInsertEventListener, | |
IPostDeleteEventListener, | |
IPostUpdateEventListener, | |
IPostCollectionUpdateEventListener | |
{ | |
public void OnPostUpdate(PostUpdateEvent ev) | |
{ | |
DispatchEvents(ev.Entity as AggregateRoot); | |
} | |
public void OnPostDelete(PostDeleteEvent ev) | |
{ | |
DispatchEvents(ev.Entity as AggregateRoot); | |
} | |
public void OnPostInsert(PostInsertEvent ev) | |
{ | |
DispatchEvents(ev.Entity as AggregateRoot); | |
} | |
public void OnPostUpdateCollection(PostCollectionUpdateEvent ev) | |
{ | |
DispatchEvents(ev.AffectedOwnerOrNull as AggregateRoot); | |
} | |
private void DispatchEvents(AggregateRoot aggregateRoot) | |
{ | |
if (aggregateRoot == null) | |
return; | |
// New functionality | |
IDomainEvent[] reduced = EventReducer.ReduceEvents(aggregateRoot.DomainEvents); | |
foreach (IDomainEvent domainEvent in reduced) | |
{ | |
Messages.Dispatch(domainEvent); | |
} | |
aggregateRoot.ClearEvents(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment