Keler.Cqrs 1.0.4

Suggested Alternatives

Kelar.Cqrs

Additional Details

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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Keler.Cqrs" Version="1.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Keler.Cqrs" Version="1.0.4" />
                    
Directory.Packages.props
<PackageReference Include="Keler.Cqrs" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Keler.Cqrs --version 1.0.4
                    
#r "nuget: Keler.Cqrs, 1.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Keler.Cqrs@1.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Keler.Cqrs&version=1.0.4
                    
Install as a Cake Addin
#tool nuget:?package=Keler.Cqrs&version=1.0.4
                    
Install as a Cake Tool

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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.4 228 6/21/2025 1.0.4 is deprecated because it is no longer maintained.
1.0.3 180 2/13/2025
1.0.2 206 2/10/2025