INotificationHandler
Namespace: RA.Utilities.Feature.Abstractions
The INotificationHandler<TNotification> interface defines the contract for a class that handles a specific INotification.
It is the "subscriber" in the publish-subscribe pattern used for eventing within the CQRS architecture.
๐ฏ Purposeโ
The primary purpose of an INotificationHandler is to contain the logic for a single side effect that should occur in response to an event.
When a notification is published using the mediator, the mediator will find all registered handlers for that specific notification type and execute their HandleAsync methods.
This pattern allows for clean separation of concerns. The code that publishes the event does not need to know what actions will be taken in response to it.
This interface is the "subscriber" part of the publish-subscribe pattern:
- Publisher: Some part of your code (like a command handler) publishes an
INotification. - Subscribers: One or more
INotificationHandlerclasses that are registered to listen for that specific notification type will have theirHandleAsyncmethod invoked.
๐ Key Characteristics:โ
| Feature | Description |
|---|---|
| Pattern | Notification โ Many Handlers (1-to-many) |
| Interface | INotificationHandler<TNotification> |
| Return value | Task (no return) |
| Mediator method | Publish() |
| Typical use case | Domain events, system events, sending emails, logging, etc. โ where multiple handlers may react independently |
- One-to-Many: A single
INotificationcan be handled by zero, one, or manyINotificationHandlerimplementations. - Decoupled Logic: It allows you to add new behaviors (like sending emails, logging, or invalidating caches) without modifying the code that triggers the event.
- Fire-and-Forget: The
HandleAsyncmethod returns aTask, not aTask<T>. This indicates that the handler performs an action but does not return a value to the publisher.
โ๏ธ How It Worksโ
- Implement the Interface: You create a class that implements
INotificationHandler<TNotification>, whereTNotificationis the specific event class you want to handle. - Implement
HandleAsync: You place your business logic for reacting to the event inside theHandleAsyncmethod. - Register the Handler: You register your handler in the dependency injection container. The mediator will then automatically discover and invoke it when the corresponding notification is published.
๐ Usage Exampleโ
Following the example from the INotification documentation, after a ProductCreatedNotification is published, you might have two separate handlers to perform different actions.
Cache Invalidation Handlerโ
This handler is responsible for clearing the cache when a new product is created.
// In Features/Caching/CacheInvalidationHandler.cs
public class CacheInvalidationHandler : INotificationHandler<ProductCreatedNotification>
{
public Task HandleAsync(ProductCreatedNotification notification, CancellationToken cancellationToken)
{
// Invalidate product cache logic here...
Console.WriteLine($"Cache invalidated for product ID: {notification.ProductId}");
return Task.CompletedTask;
}
}
Audit Log Handlerโ
This handler is responsible for writing an audit trail entry.
// In Features/Auditing/AuditLogHandler.cs
public class AuditLogHandler : INotificationHandler<ProductCreatedNotification>
{
public Task HandleAsync(ProductCreatedNotification notification, CancellationToken cancellationToken)
{
// Write to audit log logic here...
Console.WriteLine($"Audit log: Product '{notification.ProductName}' created.");
return Task.CompletedTask;
}
}
IRequestHandler ๐ INotificationHandlerโ
| Feature | IRequestHandler | INotificationHandler |
|---|---|---|
| Purpose | RequestโResponse (command/query) | PublishโSubscribe (event) |
| Mediator Method | Send() | Publish() |
| Return Type | Has a response (TResponse) | No response (void / Task) |
| Handlers | One handler per request | Multiple handlers per notification |
| Use Case | Execute logic and return a value | Broadcast an event to many subscribers |
This is fundamentally different from an IRequestHandler, which has a one-to-one relationship with its request.
An INotification can have zero, one, or many handlers.