| Branch | Status |
|---|---|
| Master | |
| Dev |
Simple CQRS library
This project composes of components for implementing the CQRS pattern (Command Handling). This library was built with simplicity, modularity and pluggability in mind.
- Send commands to registered command handlers.
- Provides simple abstraction for hosted command handlers which can be registered just like an regular command handler.
- Multiple ways of registering command handlers:
Simple handler registration (no IoC container).
IoC container registration
Attribute registration
achieved by marking methods with [CommandHandler] attributes from the Xer.Cqrs.CommandStack.Extensions.Attributes package.
See https://github.com/XerProjects/Xer.Cqrs.CommandStack.Extensions.Attributes for documentation.
You can simply clone this repository, build the source, reference the dll from the project, and code away!
Xer.Cqrs.CommandStack library is available as a Nuget package:
To install Nuget packages:
- Open command prompt
- Go to project directory
- Add the packages to the project:
dotnetadd package Xer.Cqrs.CommandStack
- Restore the packages:
dotnetrestore
(Samples are in ASP.NET Core)
// Example command.publicclassRegisterProductCommand{publicintProductId{get;}publicstringProductName{get;}publicRegisterProductCommand(intproductId,stringproductName){ProductId=productId;ProductName=productName;}}// Command handler.publicclassRegisterProductCommandHandler:ICommandAsyncHandler<RegisterProductCommand>{privatereadonlyIProductRepository_productRepository;publicRegisterProductCommandHandler(IProductRepositoryproductRepository){_productRepository=productRepository;}[CommandHandler]// This is in Xer.Cqrs.CommandStack.Extensions.Attributes. This allows the method to registered as a command handler through attribute registration.publicTaskHandleAsync(RegisterProductCommandcommand,CancellationTokencancellationToken=default(CancellationToken)){return_productRepository.SaveAsync(newProduct(command.ProductId,command.ProductName));}}Before we can delegate any commands, first we need to register our command handlers. There are several ways to do this:
// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){ ...// Repository.services.AddSingleton<IProductRepository,InMemoryProductRepository>();// Register command delegator.services.AddSingleton<CommandDelegator>((serviceProvider)=>{// Allows registration of a single message handler per message type.varregistration=newSingleMessageHandlerRegistration();registration.RegisterCommandHandler(()=>newRegisterProductCommandHandler(serviceProvider.GetRequiredService<IProductRepository>()));returnnewCommandDelegator(registration.BuildMessageHandlerResolver());});
...}// This method gets called by the runtime. Use this method to add services to the container.publicvoidConfigureServices(IServiceCollectionservices){ ...// Repository.services.AddSingleton<IProductRepository,InMemoryProductRepository>();// Register command handlers to the container. // The AddCqrs extension method is in Xer.Cqrs.Extensions.Microsoft.DependencyInjection package.services.AddCqrs(typeof(RegisterProductCommandHandler).Assembly);
...}After setting up the command delegator in the IoC container, commands can now be delegated by simply doing:
...
private readonly CommandDelegator _commandDelegator;publicProductsController(CommandDelegator commandDelegator){_commandDelegator=commandDelegator;}// POST api/products[HttpPost]publicasyncTask<IActionResult>RegisterProduct([FromBody]RegisterProductCommandDtomodel){RegisterProductCommandcommand=model.ToDomainCommand();await_commandDelegator.SendAsync(command);returnAccepted();}
...