AotCqrs 1.0.3

There is a newer version of this package available.
See the version list below for details.
dotnet add package AotCqrs --version 1.0.3
                    
NuGet\Install-Package AotCqrs -Version 1.0.3
                    
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="AotCqrs" Version="1.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AotCqrs" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="AotCqrs" />
                    
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 AotCqrs --version 1.0.3
                    
#r "nuget: AotCqrs, 1.0.3"
                    
#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 AotCqrs@1.0.3
                    
#: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=AotCqrs&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=AotCqrs&version=1.0.3
                    
Install as a Cake Tool

AotCqrs

NuGet Downloads

A blazing fast, reflection-free, AOT-friendly CQRS Mediator library for modern .NET, powered by C# Source Generators.

What is AotCqrs?

AotCqrs is a library that provides a simple way to implement the Mediator and CQRS patterns in your .NET applications, much like the popular MediatR library.

However, its core design principle is performance and compatibility with modern .NET technologies, especially Ahead-Of-Time (AOT) compilation and assembly trimming. It completely avoids runtime reflection by leveraging C# Source Generators to create highly optimized "glue" code at compile time.

This makes it an ideal choice for:

  • High-performance ASP.NET Core Minimal APIs.
  • Applications targeting NativeAOT.
  • Any scenario where startup time and runtime performance are critical.

Key Features

  • 🚀 High Performance: Zero runtime reflection. Requests are dispatched via a compile-time generated, highly optimized switch expression.
  • 📦 AOT & Trimming Safe: Designed from the ground up to work flawlessly with .NET's trimming and NativeAOT compilation.
  • ✍️ Simple & Familiar API: If you've used MediatR, you'll feel right at home with IRequest, IRequestHandler, and IMediator.
  • Compile-Time Safety: The source generator connects requests to their handlers during compilation, reducing the chance of runtime "handler not found" errors.

Why AotCqrs over MediatR?

While MediatR is a fantastic library, its reliance on reflection poses challenges for AOT compilation and can impact performance. AotCqrs addresses these specific issues.

Feature MediatR (Reflection-based) AotCqrs (Source-Generated)
Dispatch Mechanism Runtime Reflection, Assembly Scan Compile-time generated switch
AOT/Trimming Can be problematic; requires configuration Fully Compatible & Safe
Performance Good Excellent / Blazing Fast
Startup Cost Scans assemblies on startup Zero

Installation

Install the package from NuGet:

dotnet add package AotCqrs

Getting Started

Using AotCqrs is a simple, four-step process.

1. Define your Requests (Commands & Queries)

Create a record or class that implements ICommand (for requests that don't return a value) or IQuery<TResponse> (for requests that do).

// Features/Users/CreateUser.cs

using AotCqrs;

// A command to create a user. It implements ICommand, which means it returns Unit.
public record CreateUserCommand(string Name) : ICommand;

2. Create Handlers

Create a class that implements IRequestHandler<TRequest> or IRequestHandler<TRequest, TResponse>.

This is the most important part: You must mark your handler class with the [AotCqrsHandler] attribute. This is how the source generator discovers it.

// Features/Users/CreateUserCommandHandler.cs

using AotCqrs;

[AotCqrsHandler] // <-- This attribute is crucial!
public class CreateUserCommandHandler : IRequestHandler<CreateUserCommand>
{
    private readonly ILogger<CreateUserCommandHandler> _logger;

    public CreateUserCommandHandler(ILogger<CreateUserCommandHandler> logger)
    {
        _logger = logger;
    }

    public Task<Unit> Handle(CreateUserCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Creating user with name: {Name}", request.Name);
        // Your business logic here...
        return Task.FromResult(Unit.Value);
    }
}

3. Register Services

In your Program.cs, call the AddAotCqrs() extension method. The source generator automatically creates this method for you and includes the registration for all discovered handlers.

// Program.cs

using AotCqrs; // <-- Make sure to add this using directive

var builder = WebApplication.CreateBuilder(args);

// This one line registers the mediator and all handlers marked with [AotCqrsHandler].
builder.Services.AddAotCqrs();

var app = builder.Build();

// ... rest of your Program.cs

4. Send Requests

Inject IMediator into your controllers, Minimal API endpoints, or other services and use the Send method.

// Program.cs (Minimal API example)

using Microsoft.AspNetCore.Mvc;

// ...

app.MapPost("/users", async (CreateUserCommand command, [FromServices] IMediator mediator) =>
{
    await mediator.Send(command);
    return Results.Ok($"User '{command.Name}' created.");
});

app.Run();

How It Works: The Magic of Source Generators

When you build your project, the AotCqrs source generator runs and does two things:

  1. It scans your code for any class marked with [AotCqrsHandler].
  2. It generates two files on the fly:
    • DependencyInjection.g.cs: Contains the AddAotCqrs() extension method, which explicitly registers IMediator and every single handler it found. This makes it completely trimmer-friendly.
    • Mediator.g.cs: Contains the implementation of IMediator, which uses a highly optimized switch expression to route incoming requests to the correct, DI-resolved handler.

This entire process happens at compile time, resulting in clean, efficient, and boilerplate-free C# code with no runtime reflection overhead.

Contributing

Contributions are welcome! If you find a bug or have a feature request, please open an issue.

Product Compatible and additional computed target framework versions.
.NET 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 was computed.  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. 
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 149 8/18/2025
1.0.3 108 8/15/2025