Mediator.Slim 2.0.0

dotnet add package Mediator.Slim --version 2.0.0
                    
NuGet\Install-Package Mediator.Slim -Version 2.0.0
                    
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="Mediator.Slim" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Mediator.Slim" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Mediator.Slim" />
                    
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 Mediator.Slim --version 2.0.0
                    
#r "nuget: Mediator.Slim, 2.0.0"
                    
#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 Mediator.Slim@2.0.0
                    
#: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=Mediator.Slim&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Mediator.Slim&version=2.0.0
                    
Install as a Cake Tool

Mediator

NuGet .NET 10.0 License: MIT Tests

High-performance Mediator pattern implementation for .NET with CQRS support. Inspired by MediatR with focus on performance and simplicity.

โœจ Features

  • ๐Ÿš€ High Performance - Static caching, minimal allocations, aggressive inlining, zero-allocation publish for synchronous handlers
  • ๐Ÿ“ฆ CQRS Ready - Request/Response, Commands, Queries, and Notifications
  • ๐Ÿ”Œ Pipeline Behaviors - Cross-cutting concerns (logging, validation, caching)
  • โšก Streaming Support - IAsyncEnumerable for large datasets
  • ๐Ÿ›ก๏ธ Validation - Built-in validation behavior with custom validators
  • ๐ŸŽฏ Pre/Post Processors - Execute logic before/after handlers
  • ๐Ÿ’‰ DI Integration - Native Microsoft.Extensions.DependencyInjection support

๐Ÿ“ฆ Installation

dotnet add package Mediator.Slim

DI registration (AddMediator) is included in the package โ€” no extra package needed.

Requirements: .NET 10.0 or later. Use version 1.0.1 for .NET 8.0.

๐Ÿ†• What's New in 2.0.0

  • โฌ†๏ธ .NET 10 - Targets net10.0 (breaking: .NET 8 is no longer supported) with Microsoft.Extensions.* 10.0 packages.
  • ๐Ÿงฌ Polymorphic publish - Publish dispatches on the notification's runtime type, so publishing through a base type (e.g. DomainEventBase) or as object reaches the concrete type's handlers.
  • โšก Faster notifications - Publishing to 3+ handlers is non-async, uses ArrayPool, and allocates nothing when every handler completes synchronously.
Handlers (sync) 1.0.1 2.0.0
3 58 ns / 144 B 16 ns / 0 B
10 160 ns / 144 B 37 ns / 0 B
50 697 ns / 144 B 182 ns / 0 B

BenchmarkDotNet on .NET 10, publish fan-out to N handlers; the 1.0.1 column is the 1.0.1 code path run on .NET 10. For async handlers time is unchanged and allocations are lower.

๐Ÿš€ Quick Start

1. Define a Request and Handler

// Request
public record GetUserQuery(int UserId) : IRequest<UserDto>;

// Handler
public class GetUserHandler : IRequestHandler<GetUserQuery, UserDto>
{
    public async Task<UserDto> Handle(GetUserQuery request, CancellationToken ct)
    {
        return new UserDto(request.UserId, "John Doe");
    }
}

2. Register Services

services.AddMediator(config =>
{
    config.AddAssembly(typeof(Program).Assembly);
});

3. Send Requests

public class UserController
{
    private readonly IMediator _mediator;

    public UserController(IMediator mediator) => _mediator = mediator;

    public async Task<UserDto> GetUser(int id)
    {
        return await _mediator.Send(new GetUserQuery(id));
    }
}

๐Ÿ“– Usage Examples

Commands (No Response)

public record CreateUserCommand(string Name, string Email) : IRequest;

public class CreateUserHandler : IRequestHandler<CreateUserCommand, Unit>
{
    public async Task<Unit> Handle(CreateUserCommand request, CancellationToken ct)
    {
        // Create user logic
        return Unit.Value;
    }
}

Notifications (Pub/Sub)

public record UserCreated(int UserId, string Name) : INotification;

public class SendWelcomeEmail : INotificationHandler<UserCreated>
{
    public async Task Handle(UserCreated notification, CancellationToken ct)
    {
        // Send email
    }
}

public class LogUserCreated : INotificationHandler<UserCreated>
{
    public async Task Handle(UserCreated notification, CancellationToken ct)
    {
        // Log event
    }
}

// Usage
await _mediator.Publish(new UserCreated(1, "John"));

All handlers are started and awaited together; Publish completes when every handler has completed and throws if any handler fails.

Publishing through a base type dispatches to the handlers of the runtime type:

public abstract record DomainEventBase : INotification;
public record OrderCreated(int OrderId) : DomainEventBase;

DomainEventBase domainEvent = new OrderCreated(42);
await _mediator.Publish(domainEvent); // invokes INotificationHandler<OrderCreated>

Streaming (IAsyncEnumerable)

public record GetLogsStream(DateTime From) : IStreamRequest<LogEntry>;

public class GetLogsHandler : IStreamRequestHandler<GetLogsStream, LogEntry>
{
    public async IAsyncEnumerable<LogEntry> Handle(
        GetLogsStream request,
        [EnumeratorCancellation] CancellationToken ct)
    {
        await foreach (var log in _db.GetLogsAsync(request.From, ct))
        {
            yield return log;
        }
    }
}

Pipeline Behaviors

public class LoggingBehavior<TRequest, TResponse> 
    : IPipelineBehavior<TRequest, TResponse>
    where TRequest : notnull
{
    public async Task<TResponse> Handle(
        TRequest request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken ct)
    {
        _logger.LogInformation("Handling {Request}", typeof(TRequest).Name);
        
        var response = await next();
        
        _logger.LogInformation("Handled {Request}", typeof(TRequest).Name);
        return response;
    }
}

// Registration
services.AddMediator(config =>
{
    config.AddAssembly(typeof(Program).Assembly);
    config.AddBehavior(typeof(LoggingBehavior<,>));
});

Validation

public class CreateUserValidator : IValidator<CreateUserCommand>
{
    public Task<ValidationResult> ValidateAsync(
        CreateUserCommand request, 
        CancellationToken ct)
    {
        if (string.IsNullOrEmpty(request.Name))
            return Task.FromResult(
                ValidationResult.Failure("Name", "Name is required"));
        
        return Task.FromResult(ValidationResult.Success);
    }
}

// Registration
services.AddMediator(config =>
{
    config.AddAssembly(typeof(Program).Assembly);
    config.AddBehavior(typeof(ValidationBehavior<,>));
});
services.AddTransient<IValidator<CreateUserCommand>, CreateUserValidator>();

โš™๏ธ Configuration

services.AddMediator(config =>
{
    // Scan assemblies for handlers
    config.AddAssembly(typeof(Program).Assembly);
    
    // Configure lifetimes
    config.MediatorLifetime = ServiceLifetime.Scoped;
    config.HandlerLifetime = ServiceLifetime.Transient;
    config.BehaviorLifetime = ServiceLifetime.Transient;
    
    // Add behaviors (executed in order)
    config.AddBehavior(typeof(LoggingBehavior<,>));
    config.AddBehavior(typeof(ValidationBehavior<,>));
    config.AddBehavior(typeof(RequestPreProcessorBehavior<,>));
    config.AddBehavior(typeof(RequestPostProcessorBehavior<,>));
});

๐Ÿงช Testing

The library includes 84 comprehensive unit tests (xUnit v3) covering:

  • โœ… Request/Response handling
  • โœ… Notifications (single, multiple and 3+ handlers, polymorphic publish)
  • โœ… Pipeline behaviors
  • โœ… Pre/Post processors
  • โœ… Validation
  • โœ… Streaming with IAsyncEnumerable
  • โœ… Cancellation support
  • โœ… Exception handling
dotnet test

global.json opts dotnet test into Microsoft.Testing.Platform, which xUnit v3 requires on the .NET 10 SDK.

๐Ÿ“Š Project Structure

Mediator/
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ Mediator/                          # NuGet package: Mediator.Slim
โ”‚       โ”œโ”€โ”€ Abstractions/                  # Interfaces
โ”‚       โ”œโ”€โ”€ Behaviors/                     # Pipeline behaviors
โ”‚       โ”œโ”€โ”€ Exceptions/                    # Custom exceptions
โ”‚       โ”œโ”€โ”€ Validation/                    # Validation support
โ”‚       โ”œโ”€โ”€ Wrappers/                      # Handler wrappers
โ”‚       โ”œโ”€โ”€ Mediator.cs                    # Main implementation
โ”‚       โ”œโ”€โ”€ MediatorServiceConfiguration.cs
โ”‚       โ”œโ”€โ”€ ServiceCollectionExtensions.cs # AddMediator registration
โ”‚       โ””โ”€โ”€ Unit.cs                        # Unit type for void returns
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ Mediator.Tests/                    # Unit tests
โ””โ”€โ”€ benchmarks/
    โ””โ”€โ”€ Mediator.Benchmarks/               # BenchmarkDotNet vs MediatR

๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

๐Ÿ“„ License

This project is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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
2.0.0 41 10/3/2026
1.0.1 160 1/22/2026
1.0.0 131 1/14/2026