Keler.Cqrs
1.0.4
This package is deprecated and moved to Kelar.Cqrs
dotnet add package Keler.Cqrs --version 1.0.4
NuGet\Install-Package Keler.Cqrs -Version 1.0.4
<PackageReference Include="Keler.Cqrs" Version="1.0.4" />
<PackageVersion Include="Keler.Cqrs" Version="1.0.4" />
<PackageReference Include="Keler.Cqrs" />
paket add Keler.Cqrs --version 1.0.4
#r "nuget: Keler.Cqrs, 1.0.4"
#:package Keler.Cqrs@1.0.4
#addin nuget:?package=Keler.Cqrs&version=1.0.4
#tool nuget:?package=Keler.Cqrs&version=1.0.4
Keler.Cqrs
Overview
Keler.Cqrs is a lightweight CQRS (Command Query Responsibility Segregation) implementation for .NET applications. The library supports multiple .NET frameworks, including .NET Standard 2.0, .NET 6.0, .NET 8.0, and .NET 9.0, making it versatile for various project requirements.
The library provides a clean separation of concerns by implementing the CQRS pattern, allowing you to organize your code into commands (which change state) and queries (which return data) with their respective handlers.
Features
- Simple request/response pattern implementation
- Event publishing and handling capabilities
- Automatic handler registration via assembly scanning
- Support for request filters/middleware
- Easy integration with ASP.NET Core dependency injection
- Multi-targeting .NET frameworks support
Installation
dotnet add package Keler.Cqrs
Getting Started
1. Register Keler.Cqrs Services
Add Keler.Cqrs to your service collection in your Program.cs or Startup.cs file:
using Keler.Cqrs;
// ...
builder.Services.AddKelarCqrs(new[] { typeof(Program).Assembly });
2. Define Requests and Handlers
Creating a Request
Requests implement the IRequest<TResult> interface:
using Keler.Cqrs.Requests;
public class GetWeatherForecastRequest : IRequest<IEnumerable<WeatherForecast>>
{
public int Days { get; set; } = 5;
}
Implementing a Request Handler
Handlers extend the RequestHandler<TRequest, TResponse> class:
using Keler.Cqrs.Requests;
public class GetWeatherForecastRequestHandler : RequestHandler<GetWeatherForecastRequest, IEnumerable<WeatherForecast>>
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public override async Task<IEnumerable<WeatherForecast>> Handle(GetWeatherForecastRequest request, CancellationToken cancellationToken)
{
return Enumerable.Range(1, request.Days).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
});
}
}
3. Using the Request Dispatcher
Inject IRequestDispatcher into your controllers or services:
using Keler.Cqrs.Requests;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly IRequestDispatcher _dispatcher;
public WeatherForecastController(IRequestDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
[HttpGet]
public async Task<IEnumerable<WeatherForecast>> Get()
{
return await _dispatcher.Dispatch(new GetWeatherForecastRequest());
}
}
Event Handling
1. Define Events
Events implement the IEvent interface:
using Keler.Cqrs.Events;
public class WeatherForecastCreatedEvent : IEvent
{
public Guid Id { get; } = Guid.NewGuid();
public WeatherForecast Forecast { get; set; }
}
2. Implement Event Handlers
Event handlers implement the IEventHandler<TEvent> interface:
using Keler.Cqrs.Events;
public class WeatherForecastEventHandler : IEventHandler<WeatherForecastCreatedEvent>
{
private readonly ILogger<WeatherForecastEventHandler> _logger;
public WeatherForecastEventHandler(ILogger<WeatherForecastEventHandler> logger)
{
_logger = logger;
}
public Task Handle(WeatherForecastCreatedEvent @event, CancellationToken cancellationToken)
{
_logger.LogInformation("Weather forecast created: {Temp}°C, {Summary}",
@event.Forecast.TemperatureC,
@event.Forecast.Summary);
return Task.CompletedTask;
}
}
3. Publishing Events
Request handlers have direct access to an EventPublisher property which can be used to publish events:
using Keler.Cqrs.Requests;
using Keler.Cqrs.Events;
public class CreateWeatherForecastHandler : RequestHandler<CreateWeatherForecastRequest, WeatherForecast>
{
public override async Task<WeatherForecast> Handle(CreateWeatherForecastRequest request, RequestContext context, CancellationToken cancellationToken = default)
{
// Create forecast logic...
var forecast = new WeatherForecast
{
Date = DateTime.Now.AddDays(1),
TemperatureC = request.Temperature,
Summary = request.Summary
};
// Publish event using the EventPublisher property
_ = EventPublisher.Publish(new WeatherForecastCreatedEvent
{
Forecast = forecast
});
return forecast;
}
}
Request Filters
You can implement request filters to add cross-cutting concerns like logging, validation, or authorization:
using Keler.Cqrs.Requests;
using Microsoft.Extensions.Logging;
public class LoggingRequestFilter : IRequestsFilter
{
private readonly ILogger<LoggingRequestFilter> _logger;
public LoggingRequestFilter(ILogger<LoggingRequestFilter> logger)
{
_logger = logger;
}
public async Task<TResponse> OnRequestExecuting<TResponse>(IRequest<TResponse> request, RequestContext context)
{
_logger.LogInformation("Executing request {RequestType}", typeof(request).Name);
var stopwatch = Stopwatch.StartNew();
try
{
var result = await context.Next(request, cancellationToken);
stopwatch.Stop();
_logger.LogInformation("Request {RequestType} executed in {ElapsedMs}ms",
typeof(request).Name, stopwatch.ElapsedMilliseconds);
return result;
}
catch (Exception ex)
{
stopwatch.Stop();
_logger.LogError(ex, "Request {RequestType} failed after {ElapsedMs}ms",
typeof(request).Name, stopwatch.ElapsedMilliseconds);
throw;
}
}
}
Register the filter in your service configuration:
builder.Services.AddSingleton<IRequestsFilter, LoggingRequestFilter>();
Advanced Configuration
Including Internal Types
By default, only public types are scanned. To include internal types:
builder.Services.AddKelarCqrs(
new[] { typeof(Program).Assembly },
includeInternalTypes: true);
Supported Frameworks
- .NET Standard 2.0
- .NET 6.0
- .NET 8.0
- .NET 9.0
License
This project is licensed under the MIT License—see the LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
-
net6.0
-
net8.0
-
net9.0
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.