Comandante is a small and simple library that was created to make development of CQRS applications easier.
Install the package via NuGet first:
Install-Package Commandante
Comandante has separate pipeline for commands and queries. That principle let you optimize processing commands and queries independently from one another.
Comandante rests on dependency injection to create command and query handlers. So to work correctly you have to add some of supported DI library such as:
- Comandante.Extensions.Microsoft.DependencyInjection
Otherwise, you have to implement IServiceFactory
public class ServiceFactory : IServiceFactory
{
public object GetService(Type serviceType)
{
// Creates a new service
}
}
To register all necessary Comandante handlers and dispatchers you can use Commandante.Extensions.Microsoft.DependencyInjection method
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddComandate(Assembly);
}
Comandante provides two types of messages:
ICommand
for command operations that create somethingIQuery
for query operations that retrieve some information
Command message is just a simple POCO class that implements ICommand
interface
public class CreateUserCommand : ICommand<long>
{
public CreateUserCommand(string userName)
{
UserName = userName;
}
public string UserName { get; }
}
Next, create a handler:
public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, long>
{
public Task<long> Handle(CreateUserCommand command, CancellationToken cancellationToken)
{
return Task.FromResult(42l);
}
}
Finally, send a command through the command dispatcher ICommandDispatcher
:
var cmd = new CreateUserCommand("test");
var userId = await dispatcher.Dispatch(cmd, default);
Debug.WriteLine(userId); // 42
Query message is also a simple POCO class that implements IQuery
interface
public class GetUserQuery : IQuery<User>
{
public GetUserQuery(long userId)
{
UserId = userId;
}
public long UserId { get; }
}
Next, create a handler:
public record User(long UserId, string UserName);
public class GetUserQueryHandler : IQueryHandler<GetUserQuery, User>
{
public Task<User> Handle(GetUserQuery query, CancellationToken cancellationToken)
{
return Task.FromResult(new User(42, "The one"));
}
}
Finally, send a query through the query dispatcher IQueryDispatcher
:
var query = new GetUserQuery(42)
var user = await dispatcher.Dispatch(query, default);
Debug.WriteLine(user.ToString()); // User { UserId = 42, UserName = The one }