Branch | Status |
---|---|
Master | |
Dev |
Simple CQRS library
This project composes of components for implementing the CQRS pattern (Event Handling). This library was built with simplicity, modularity and pluggability in mind.
- Send event to registered event handlers.
- Provides simple abstraction for hosted event handlers which can be registered just like an regular event handler.
- Multiple ways of registering event handlers:
-
Simple handler registration (no IoC container).
-
IoC container registration
-
Attribute registration
-
achieved by marking methods with [EventHandler] attributes from the Xer.Cqrs.EventStack.Extensions.Attributes package.
-
See https://github.com/XerProjects/Xer.Cqrs.EventStack.Extensions.Attributes for documentation.
-
-
You can simply clone this repository, build the source, reference the dll from the project, and code away!
Xer.Cqrs.EventStack library is available as a Nuget package:
To install Nuget packages:
- Open command prompt
- Go to project directory
- Add the packages to the project:
dotnet add package Xer.Cqrs.EventStack
- Restore the packages:
dotnet restore
(Samples are in ASP.NET Core)
public class ProductRegisteredEvent
{
public int ProductId { get; }
public string ProductName { get; }
public ProductRegisteredEvent(int productId, string productName)
{
ProductId = productId;
ProductName = productName;
}
}
// Sync event handler
public class ProductRegisteredEventHandler : IEventHandler<ProductRegisteredEvent>
{
public void Handle(ProductRegisteredEvent @event)
{
System.Console.WriteLine($"ProductRegisteredEventHandler handled {@event.GetType()}.");
}
}
// Async event handler
public class ProductRegisteredEmailNotifier : IEventAsyncHandler<ProductRegisteredEvent>
{
public Task HandleAsync(ProductRegisteredEvent @event, CancellationToken ct = default(CancellationToken))
{
System.Console.WriteLine($"Sending email notification...");
return Task.CompletedTask;
}
}
Before we can delegate any events, first, we need to register our event handlers. There are several ways to do this:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
...
// Repository.
services.AddSingleton<IProductRepository, InMemoryProductRepository>();
// Register event delegator.
services.AddSingleton<EventDelegator>((serviceProvider) =>
{
// Allows registration of a multiple message handlers per message type.
var registration = new MultiMessageHandlerRegistration();
registration.RegisterEventHandler<ProductRegisteredEvent>(() => new ProductRegisteredEventHandler());
registration.RegisterEventHandler<ProductRegisteredEvent>(() => new ProductRegisteredEmailNotifier());
return new EventDelegator(registration.BuildMessageHandlerResolver());
});
...
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
...
// Repository.
services.AddSingleton<IProductRepository, InMemoryProductRepository>();
// Register event handlers to the container.
// The AddCqrs extension method is in Xer.Cqrs.Extensions.Microsoft.DependencyInjection package.
services.AddCqrs(typeof(ProductRegisteredEventHandler).Assembly);
...
}
After setting up the event delegator in the Ioc container, events can now be delegated by simply doing:
...
private readonly EventDelegator _eventDelegator;
public ProductsController(EventDelegator eventDelegator)
{
_eventDelegator = eventDelegator;
}
[HttpGet("{productId}")]
public async Task<IActionResult> Notify(ProductRegisteredEventDto model)
{
await _eventDelegator.SendAsync(new ProductRegisteredEvent(model.ProductId, model.ProductName))
return Accepted();
}
...