-
Notifications
You must be signed in to change notification settings - Fork 13
Event Module
Events are informative messages designed to notify various parts of a system about certain occurrences. A distinct feature of events compared to commands and queries is that they can have multiple main handlers, allowing several operations or components of your system to react to a single event.
To define your own events, implement the IEvent interface:
// A simple event representation
public class ProductCreatedEvent : IEvent
{
public long Id { get; set; }
}Handlers process or act upon events. Due to the nature of events, they can have multiple handlers, which means different components of your system can respond simultaneously to an event.
// Sample asynchronous event handler
public class ProductCreatedEventHandler1 : IEventHandler<ProductCreatedEvent>
{
public Task HandleAsync(ProductCreatedEvent @event, CancellationToken cancellationToken = default)
{
// Handle the event here...
}
}
// Another sample asynchronous event handler for the same event
public class ProductCreatedEventHandler2 : IEventHandler<ProductCreatedEvent>
{
public Task HandleAsync(ProductCreatedEvent @event, CancellationToken cancellationToken = default)
{
// Handle the event here...
}
}Use the IEventMediator to publish events to their respective handlers. This ensures that all relevant handlers are informed of an event occurrence.
public interface IEventMediator
{
Task PublishAsync(IEvent @event, CancellationToken cancellationToken = default);
Task PublishAsync<TEvent>(TEvent @event, CancellationToken cancellationToken = default) where TEvent : IEvent;
}Pre-handlers are executed before the main event handlers, useful for activities like validation or logging.
public class ProductEventPreHandler : IEventPreHandler<ProductCreatedEvent>
{
public Task PreHandleAsync(ProductCreatedEvent @event, CancellationToken cancellationToken = default)
{
// Logic before the main event handler...
}
}public class GlobalEventPreHandler : IEventPreHandler
{
public Task PreHandleAsync(IEvent @event, CancellationToken cancellationToken = default)
{
// Logic before any event handler...
}
}Post-handlers run after the main event handlers, typically for activities like logging, notifications, or other follow-up actions.
public class ProductEventPostHandler : IEventPostHandler<ProductCreatedEvent>
{
public Task PostHandleAsync(ProductCreatedEvent @event, CancellationToken cancellationToken = default)
{
// Logic after the main event handler...
}
}public class GlobalEventPostHandler : IEventPostHandler
{
public Task PostHandleAsync(IEvent @event, CancellationToken cancellationToken = default)
{
// Logic after any event handler...
}
}These handlers are activated when there's an exception during event processing. They offer a centralized way to manage and respond to errors.
public class ProductEventErrorHandler : IEventErrorHandler<ProductCreatedEvent>
{
public Task HandleErrorAsync(ProductCreatedEvent @event, Exception exception, CancellationToken cancellationToken = default)
{
// Handle the error for a specific event type here...
}
}public class GlobalEventErrorHandler : IEventErrorHandler
{
public Task HandleErrorAsync(IEvent @event, Exception exception, CancellationToken cancellationToken = default)
{
// Handle the error for any event type...
}
}Event handlers can be filtered based on a custom condition. For example, you may wish only to execute those event handlers inheriting from the IHighPriorityEventHandler interface.
// Example of using EventMediationSettings to filter event handlers
// that implement the IHighPriorityEventHandler interface
await eventMediator.PublishAsync(@event, new EventMediationSettings
{
HandlerFilter = type => type.IsAssignableTo(typeof(IHighPriorityEventHandler))
});