-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace Ardalis.SharedKernel; | ||
|
||
public interface IHasDomainEvents | ||
{ | ||
IReadOnlyCollection<DomainEventBase> DomainEvents { get; } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,38 @@ | ||
using System; | ||
using MediatR; | ||
using MediatR; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Ardalis.SharedKernel; | ||
|
||
public class MediatRDomainEventDispatcher : IDomainEventDispatcher | ||
{ | ||
private readonly IMediator _mediator; | ||
private readonly ILogger<MediatRDomainEventDispatcher> _logger; | ||
|
||
public MediatRDomainEventDispatcher(IMediator mediator) | ||
public MediatRDomainEventDispatcher(IMediator mediator, ILogger<MediatRDomainEventDispatcher> logger) | ||
{ | ||
_mediator = mediator; | ||
_logger = logger; | ||
} | ||
|
||
public async Task DispatchAndClearEvents(IEnumerable<EntityBase> entitiesWithEvents) | ||
public async Task DispatchAndClearEvents(IEnumerable<IHasDomainEvents> entitiesWithEvents) | ||
{ | ||
foreach (var entity in entitiesWithEvents) | ||
foreach (IHasDomainEvents entity in entitiesWithEvents) | ||
{ | ||
var events = entity.DomainEvents.ToArray(); | ||
entity.ClearDomainEvents(); | ||
foreach (var domainEvent in events) | ||
if (entity is HasDomainEventsBase hasDomainEvents) | ||
{ | ||
await _mediator.Publish(domainEvent).ConfigureAwait(false); | ||
DomainEventBase[] events = hasDomainEvents.DomainEvents.ToArray(); | ||
hasDomainEvents.ClearDomainEvents(); | ||
|
||
foreach (DomainEventBase domainEvent in events) | ||
await _mediator.Publish(domainEvent).ConfigureAwait(false); | ||
} | ||
} | ||
} | ||
|
||
public async Task DispatchAndClearEvents<TId>(IEnumerable<EntityBase<TId>> entitiesWithEvents) | ||
where TId : struct, IEquatable<TId> | ||
{ | ||
foreach (var entity in entitiesWithEvents) | ||
{ | ||
var events = entity.DomainEvents.ToArray(); | ||
entity.ClearDomainEvents(); | ||
foreach (var domainEvent in events) | ||
else | ||
{ | ||
await _mediator.Publish(domainEvent).ConfigureAwait(false); | ||
_logger.LogError( | ||
"Entity of type {EntityType} does not inherit from {BaseType}. Unable to clear domain events.", | ||
entity.GetType().Name, | ||
nameof(HasDomainEventsBase)); | ||
} | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using FluentAssertions; | ||
using MediatR; | ||
using Microsoft.Extensions.Logging.Abstractions; | ||
using Moq; | ||
using Xunit; | ||
|
||
namespace Ardalis.SharedKernel.UnitTests.MediatRDomainEventDispatcherTests; | ||
|
||
public class DispatchAndClearEventsWithMixedIds | ||
{ | ||
private class TestDomainEvent : DomainEventBase { } | ||
public readonly record struct StronglyTyped { } | ||
|
||
private class TestEntity : EntityBase | ||
{ | ||
public void AddTestDomainEvent() | ||
{ | ||
TestDomainEvent domainEvent = new(); | ||
RegisterDomainEvent(domainEvent); | ||
} | ||
} | ||
private class TestEntityGuid : EntityBase<Guid> | ||
{ | ||
public void AddTestDomainEvent() | ||
{ | ||
TestDomainEvent domainEvent = new(); | ||
RegisterDomainEvent(domainEvent); | ||
} | ||
} | ||
private class TestEntityStronglyTyped : EntityBase<StronglyTyped> | ||
{ | ||
public void AddTestDomainEvent() | ||
{ | ||
TestDomainEvent domainEvent = new(); | ||
RegisterDomainEvent(domainEvent); | ||
} | ||
} | ||
|
||
[Fact] | ||
public async void CallsPublishAndClearDomainEventsWithStronglyTypedId() | ||
Check failure on line 40 in tests/Ardalis.SharedKernel.UnitTests/MediatRDomainEventDispatcherTests/DispatchAndClearEventsWithMixedIds.cs GitHub Actions / build
Check failure on line 40 in tests/Ardalis.SharedKernel.UnitTests/MediatRDomainEventDispatcherTests/DispatchAndClearEventsWithMixedIds.cs GitHub Actions / build
|
||
{ | ||
// Arrange | ||
var mediatorMock = new Mock<IMediator>(); | ||
var domainEventDispatcher = new MediatRDomainEventDispatcher(mediatorMock.Object, NullLogger<MediatRDomainEventDispatcher>.Instance); | ||
var entity = new TestEntity(); | ||
var entityGuid = new TestEntityGuid(); | ||
var entityStronglyTyped = new TestEntityStronglyTyped(); | ||
entity.AddTestDomainEvent(); | ||
entityGuid.AddTestDomainEvent(); | ||
entityStronglyTyped.AddTestDomainEvent(); | ||
|
||
// Act | ||
await domainEventDispatcher.DispatchAndClearEvents(new List<IHasDomainEvents> { entity, entityGuid, entityStronglyTyped }); | ||
|
||
// Assert | ||
mediatorMock.Verify(m => m.Publish(It.IsAny<DomainEventBase>(), It.IsAny<CancellationToken>()), Times.Exactly(3)); | ||
entity.DomainEvents.Should().BeEmpty(); | ||
entityGuid.DomainEvents.Should().BeEmpty(); | ||
entityStronglyTyped.DomainEvents.Should().BeEmpty(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using FluentAssertions; | ||
using MediatR; | ||
using Microsoft.Extensions.Logging.Abstractions; | ||
using Moq; | ||
using Xunit; | ||
|
||
namespace Ardalis.SharedKernel.UnitTests.MediatRDomainEventDispatcherTests; | ||
|
||
public class DispatchAndClearEventsWithStronglyTypedIds | ||
{ | ||
private class TestDomainEvent : DomainEventBase { } | ||
|
||
public readonly record struct StronglyTyped { } | ||
|
||
private class TestEntityStronglyTyped : EntityBase<StronglyTyped> | ||
{ | ||
public void AddTestDomainEvent() | ||
{ | ||
TestDomainEvent domainEvent = new(); | ||
RegisterDomainEvent(domainEvent); | ||
} | ||
} | ||
|
||
[Fact] | ||
public async void CallsPublishAndClearDomainEventsWithStronglyTypedId() | ||
Check failure on line 25 in tests/Ardalis.SharedKernel.UnitTests/MediatRDomainEventDispatcherTests/DispatchAndClearEventsWithStronglyTypedIds.cs GitHub Actions / build
Check failure on line 25 in tests/Ardalis.SharedKernel.UnitTests/MediatRDomainEventDispatcherTests/DispatchAndClearEventsWithStronglyTypedIds.cs GitHub Actions / build
|
||
{ | ||
// Arrange | ||
Mock<IMediator> mediatorMock = new Mock<IMediator>(); | ||
MediatRDomainEventDispatcher domainEventDispatcher = | ||
new(mediatorMock.Object, NullLogger<MediatRDomainEventDispatcher>.Instance); | ||
TestEntityStronglyTyped entity = new(); | ||
entity.AddTestDomainEvent(); | ||
|
||
// Act | ||
await domainEventDispatcher.DispatchAndClearEvents(new List<IHasDomainEvents> { entity }); | ||
|
||
// Assert | ||
mediatorMock.Verify(m => m.Publish(It.IsAny<DomainEventBase>(), It.IsAny<CancellationToken>()), Times.Once); | ||
entity.DomainEvents.Should().BeEmpty(); | ||
} | ||
} |