Smpl.Mediatr 2.0.0

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

Smpl.Mediatr

A lightweight mediator pattern implementation for .NET 9/10, providing a simple and clean abstraction for handling commands and queries in your applications using CQRS (Command Query Responsibility Segregation) principles.

Overview

This project implements the mediator pattern to decouple request/response handling in your application. It provides a clean separation between commands (operations that change state) and queries (operations that retrieve data), promoting clean architecture and separation of concerns.

Features

  • Command Pattern: Execute operations with or without return values
  • Query Pattern: Retrieve data without side effects
  • Mediator Pattern: Centralized request routing and handling using dependency injection
  • Automatic Handler Registration: Automatically discovers and registers all handlers from assemblies
  • Async/Await Support: Full async support with cancellation tokens
  • Lightweight: Minimal dependencies (only Microsoft.Extensions.DependencyInjection.Abstractions)
  • .NET 9/10: Built for the latest .NET platform with nullable reference types enabled

Project Structure

base-mediatr/
├── Extension/
│   └── ServiceCollectionExtensions.cs  # Automatic handler registration extension
├── Mediator/
│   ├── ICommand.cs          # Command interface definitions (with and without return values)
│   ├── ICommandHandler.cs   # Command handler interfaces
│   ├── IMediator.cs         # Main mediator interface
│   └── IQuery.cs           # Query interface and handler definitions
├── Mediator.cs             # Main mediator implementation
└── base-mediatr.csproj     # Project file

Pipeline behaviors and notifications (2.0.0)

services.AddMediator(typeof(Program).Assembly);           // handlers (commands, queries, notifications) are scanned
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));   // behaviors are NOT scanned;
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); // first registered = outermost
  • IPipelineBehavior<TRequest, TResult> wraps commands (both forms) and queries. A command without a result flows with TResult = Unit.
  • INotification / INotificationHandler<T> / IPublisher.PublishAsync: handlers run sequentially, the first exception propagates. IMediator : IPublisher.
  • Handler exceptions propagate unwrapped (typed dispatch, no reflection invoke).
  • Namespace is Smpl.Mediatr (package id Smpl.Mediatr). The parameterless AddMediator() is obsolete.

Releases: bump <Version>, push a tag vX.Y.Z; the publish workflow uses the repository secret NUGET_API_KEY.

Getting Started

Prerequisites

  • .NET 9/10 SDK
  • Microsoft.Extensions.DependencyInjection (for DI container)

Installation

Clone the repository:

git clone <repository-url>
cd base-mediatr

Build the project:

dotnet build

Basic Usage

1. Define Commands and Queries
// Command with return value
public record CreateUserCommand(string Name, string Email) : ICommand<int>;

// Command without return value
public record DeleteUserCommand(int UserId) : ICommand;

// Query
public record GetUserQuery(int UserId) : IQuery<User>;
2. Implement Handlers
public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, int>
{
    public async Task<int> HandleAsync(CreateUserCommand command, CancellationToken cancellationToken = default)
    {
        // Create user logic
        return userId;
    }
}

public class DeleteUserCommandHandler : ICommandHandler<DeleteUserCommand>
{
    public async Task HandleAsync(DeleteUserCommand command, CancellationToken cancellationToken = default)
    {
        // Delete user logic
    }
}

public class GetUserQueryHandler : IQueryHandler<GetUserQuery, User>
{
    public async Task<User> HandleAsync(GetUserQuery query, CancellationToken cancellationToken = default)
    {
        // Get user logic
        return user;
    }
}
3. Register Services

The easiest way to register the mediator and all handlers is using the extension method:

using Smpl.Mediatr.Extension;

// Register mediator and automatically discover all handlers in the current assembly
services.AddMediator();

// Or specify specific assemblies to scan
services.AddMediator(typeof(CreateUserCommandHandler).Assembly, typeof(AnotherHandler).Assembly);

The AddMediator() extension method will:

  • Register the IMediator service
  • Automatically scan assemblies for all handler implementations
  • Register all found handlers with the DI container
Manual Registration

If you prefer manual registration:

services.AddScoped<IMediator, Mediator>();
services.AddScoped<ICommandHandler<CreateUserCommand, int>, CreateUserCommandHandler>();
services.AddScoped<ICommandHandler<DeleteUserCommand>, DeleteUserCommandHandler>();
services.AddScoped<IQueryHandler<GetUserQuery, User>, GetUserQueryHandler>();
4. Use the Mediator
public class UserController : ControllerBase
{
    private readonly IMediator _mediator;

    public UserController(IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpPost]
    public async Task<int> CreateUser(CreateUserCommand command)
    {
        return await _mediator.SendAsync(command);
    }

    [HttpDelete("{id}")]
    public async Task DeleteUser(int id)
    {
        await _mediator.SendAsync(new DeleteUserCommand(id));
    }

    [HttpGet("{id}")]
    public async Task<User> GetUser(int id)
    {
        return await _mediator.SendAsync(new GetUserQuery(id));
    }
}

Key Interfaces

IMediator

The main interface for sending commands and queries:

  • Task<TResult> SendAsync<TResult>(ICommand<TResult> command, CancellationToken cancellationToken = default)
  • Task SendAsync(ICommand command, CancellationToken cancellationToken = default)
  • Task<TResult> SendAsync<TResult>(IQuery<TResult> query, CancellationToken cancellationToken = default)

Commands

  • ICommand<TResult>: Commands that return a value
  • ICommand: Commands that don't return a value
  • ICommandHandler<TCommand, TResult>: Handler for commands with return values
  • ICommandHandler<TCommand>: Handler for commands without return values

Queries

  • IQuery<TResult>: Query interface that returns data
  • IQueryHandler<TQuery, TResult>: Handler for queries

Automatic Handler Registration

The ServiceCollectionExtensions.AddMediator() method provides automatic handler discovery and registration:

Assembly Scanning

  • No parameters: Scans executing, calling, entry, and all loaded assemblies
  • With assemblies: Scans only the specified assemblies

Handler Discovery

The extension automatically finds and registers:

  • All classes implementing ICommandHandler<TCommand, TResult>
  • All classes implementing ICommandHandler<TCommand>
  • All classes implementing IQueryHandler<TQuery, TResult>

Registration Scope

All handlers are registered as Scoped services, which is appropriate for most web applications and ensures proper lifecycle management.

Architecture Benefits

  • Separation of Concerns: Clear separation between business logic and controllers
  • Testability: Easy to unit test handlers in isolation
  • Maintainability: Changes to business logic don't affect controllers
  • Scalability: Easy to add new commands and queries without modifying existing code
  • CQRS: Natural implementation of Command Query Responsibility Segregation
  • Convention-based: Automatic registration reduces boilerplate code

Dependencies

  • Microsoft.Extensions.DependencyInjection.Abstractions (9.0.9)

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Inspired by the MediatR library
  • Built with .NET 9/10 and modern C# features
Product Compatible and additional computed target framework versions.
.NET 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 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 91 10/21/2026