Ardalis.SharedKernel
Ardalis.SharedKernel copied to clipboard
Support for HasDomainEventsBase in the DomainEventDispatcher
I'm employing strongly typed Ids in my entities. Consequently, I'm unable to utilize DispatchAndClearEvents()
. Instead, I can resort to DispatchAndClearEvents<TId>()
. However, this requires manual definition of each entity which will become cumbersome for larger projects, for example:
public async Task SaveChangesAsync(CancellationToken cancellationToken = default)
{
UpdateAuditableEntities();
await dbContext.SaveChangesAsync(cancellationToken);
await HandleDomainEvents<CustomerId>();
await HandleDomainEvents<OrderId>();
await HandleDomainEvents<OrderLineId>();
await HandleDomainEvents<ProductId>();
// etc.
}
private Task HandleDomainEvents<TId>() where TId : struct, IEquatable<TId>
{
if (dispatcher is null)
return Task.CompletedTask;
EntityBase<TId>[] entitiesWithEvents = dbContext.ChangeTracker
.Entries<EntityBase<TId>>()
.Select(e => e.Entity)
.Where(e => e.DomainEvents.Any())
.ToArray();
return dispatcher.DispatchAndClearEvents(entitiesWithEvents);
}
I was wondering why the current code is written with EntityBase
in mind and not the underlying HasDomainEventBase
? You would be able to define the following and omit the other two methods:
public async Task DispatchAndClearEvents(IEnumerable<HasDomainEventsBase> entitiesWithEvents)
{
foreach (HasDomainEventsBase entity in entitiesWithEvents)
{
DomainEventBase[] events = entity.DomainEvents.ToArray();
entity.ClearDomainEvents();
foreach (DomainEventBase domainEvent in events)
{
await mediator.Publish(domainEvent).ConfigureAwait(false);
}
}
}
Correct? Or is the Id
of the EntityBase
necessary for the DbContext.ChangeTracker
? If so, what would be a good approach here?