Domain Events with .NET - New Features
Introduction
You may remember my post on the Domain Events framework I created, a few days ago. Well, I've been working on it, cleaning things a bit, correcting a few bugs, and I introduced two new features/concept:
- Event interceptors can now return a boolean from the BeforePublish event in order to cancel the publication of the event
- Event transformers
Changes to Event Interceptors
The changes to the IDomainEventInterceptor/IDomainEventInterceptor<TEvent> interface look like this:
public interface IDomainEventInterceptor
{
ValueTask<bool> BeforePublish(IDomainEvent @event, CancellationToken cancellationToken = default);
Task AfterPublish(IDomainEvent @event, CancellationToken cancellationToken = default);
}
public interface IDomainEventInterceptor<TEvent> where TEvent : IDomainEvent
{
ValueTask<bool> BeforePublish(TEvent @event, CancellationToken cancellationToken = default);
Task AfterPublish(TEvent @event, CancellationToken cancellationToken = default);
}
As you can see, the only change is that now the BeforePublish method returns a ValueTask<bool>. The idea is, if you want to cancel the publication of an event, you return false from it, otherwise, true (which is the default). Note that if you cancel an event publication, all the other interceptors will not be fired. The order by which they are called is LIFO - Last In, First Out.
Event Transformers
Event transformers are essentially a Func<TSourceEvent, TTargetEvent> that takes an event and turns it into another. When publishing an event, the framework will check if there is a registered transformer and will call it. The resulting type must also be an event (implement IDomainEvent).
This required a change to the IEventsMediator interface, which now has one more method:
public interface IEventsMediator
{
void AddTransformer<TSourceEvent, TTargetEvent>(Func<TSourceEvent, TTargetEvent> transformer) where TSourceEvent : IDomainEvent where TTargetEvent : IDomainEvent;;
}
To use it, we call it from the mediator instance:
mediator.AddTransformer<AbcEvent, XyzEvent>(e => new XyzEvent());
Conclusion
Both the source code and the Nuget package have been updated, the new version is now 2.0.
Do let me know what you think of this, if you use or plan to use it, or if you have any bug reports/issues that you'd like to see addressed! Disagreements are also welcome too! ;-)
Two suggestions from my experience using MediatR: 1. Make sure the add events scanning method can be called multiple times without duplicating subscriptions. 2. Have some facility for verifying the existence of a handler for each event as the decoupled nature of the pattern leads to fear that a critical event will be fired and nobody will be there to handle it.
ReplyDeleteThanks for the comment. You're right about #1, I need to find a way to address this. As for #2, I made it support the two scenarios, there's a configuration flag that will cause an exception to be thrown if there are no handlers. What are your thoughts on this?
DeleteBTW, I'm a big fan of MediatR, but my framework is slightly different, as there is no way to return responses, it's essentially an event publishing/subscription framework.
Delete