Mediatron 1.0.1

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

Mediatron

Mediatron is a small, fast, and easy-to-understand mediator library for .NET.

It helps you keep your code clean by separating "what to do" (a request) from "how to do it" (a handler). This pattern is often called CQRS (Command Query Responsibility Segregation), and Mediatron also supports events (Pub/Sub) so different parts of your app can react to something that happened, without knowing about each other.

Think of Mediatron as a post office for your application:

  • You write a letter (a request or a notification).
  • You hand it to the mediator (the post office).
  • The mediator finds the right person (the handler) and delivers it.
  • You never need to know who the handler is or where it lives — the mediator takes care of that.

Why would I use this?

Without a mediator, your controllers and services end up calling many other services directly, and everything becomes tightly connected and hard to test.

With Mediatron:

  • Your controller only talks to IMediator.
  • Each piece of business logic lives in its own small, focused handler class.
  • Adding new features means adding a new file, not editing old ones.
  • It's easy to unit test each handler on its own.

Features

Feature What it means
✅ Zero Bloat Small codebase, no unnecessary dependencies.
✅ CQRS Support Send commands and queries with strong typing.
✅ Pub/Sub Notifications One event can be handled by many listeners at once.
✅ Pipeline Behaviors Add cross-cutting logic (logging, validation, etc.) around your handlers.
✅ Native DI Integration Works directly with Microsoft.Extensions.DependencyInjection.
✅ Fully Tested Covered by unit tests (xUnit, FluentAssertions, NSubstitute).
✅ XML Documented Full IntelliSense/documentation comments in the source code.

Requirements

  • .NET 10.0 or later
  • Microsoft.Extensions.DependencyInjection

Installation

Install Mediatron from NuGet using the .NET CLI:

dotnet add package Mediatron

Getting Started

This section walks you through the basics step by step, using a simple "create a product" example.

Step 1 — Register Mediatron

Mediatron scans one assembly (usually your own project) and automatically finds and registers every handler it can find. You only need to do this once, when you set up your app.

using Mediatron;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// Scan the current assembly for handlers and register everything Mediatron needs
builder.Services.AddMediatron(typeof(Program).Assembly);

var app = builder.Build();

Step 2 — Create a Request

A request describes what you want to happen. There are two kinds:

  • IRequest — "do something", no result expected (like a command that just performs an action).
  • IRequest<TResponse> — "do something and give me a result back".
using Mediatron;

// A request that returns an int (the new product's id)
public record CreateProductCommand(string Name, decimal Price) : IRequest<int>;

Step 3 — Create a Handler

A handler describes how to do it. Every request needs exactly one matching handler.

using Mediatron;

public class CreateProductCommandHandler : IRequestHandler<CreateProductCommand, int>
{
    public async Task<int> Handle(CreateProductCommand request, CancellationToken cancellationToken)
    {
        // Put your business logic here, e.g. save the product to a database
        int generatedId = 42;

        return await Task.FromResult(generatedId);
    }
}

Step 4 — Send the Request

Inject IMediator wherever you need it (for example, in an ASP.NET Core controller) and call SendAsync.

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IMediator _mediator;

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

    [HttpPost]
    public async Task<IActionResult> Create([FromBody] CreateProductCommand command)
    {
        var productId = await _mediator.SendAsync<CreateProductCommand, int>(command);
        return Ok(new { ProductId = productId });
    }
}

If your request does not return a value, just implement IRequest and call the simpler overload:

public record DeleteProductCommand(int ProductId) : IRequest;

await _mediator.SendAsync(deleteCommand);

Notifications (Events)

Sometimes one thing happening should trigger several independent reactions — for example, "a product was created" might need to update stock and send an email. This is what notifications are for.

Unlike a request, a notification can have zero, one, or many handlers, and every registered handler will be called.

// 1. Define the event
public record ProductCreatedEvent(int ProductId, string ProductName) : INotification;

// 2. Handler A – updates stock
public class NotifyStockSystemHandler : INotificationHandler<ProductCreatedEvent>
{
    public async Task Handle(ProductCreatedEvent notification, CancellationToken cancellationToken)
    {
        // update stock system...
        await Task.CompletedTask;
    }
}

// 3. Handler B – sends an email
public class SendEmailToAdminHandler : INotificationHandler<ProductCreatedEvent>
{
    public async Task Handle(ProductCreatedEvent notification, CancellationToken cancellationToken)
    {
        // send email...
        await Task.CompletedTask;
    }
}

// 4. Publish the event — both handlers above will run
await _mediator.PublishAsync(new ProductCreatedEvent(42, "Laptop"));

Pipeline Behaviors (Advanced)

A pipeline behavior lets you run code before and after a handler runs — without touching the handler itself. This is great for things like logging, validation, or timing.

public class DeleteProductIdValidationBehavior : IPipelineBehavior<DeleteProductCommand>
{
    public async Task Handle(
        DeleteProductCommand request,
        RequestHandlerDelegate next,
        CancellationToken cancellationToken)
    {
        if (request.ProductId <= 0)
            throw new ArgumentException("Product Id must be greater than zero.");

        // Call the next step in the pipeline (this eventually calls the handler)
        await next();
    }
}

Mediatron automatically discovers and registers any class that implements IPipelineBehavior<TRequest> or IPipelineBehavior<TRequest, TResponse> when you call AddMediatron.


Full Working Example

The repository includes a runnable console sample at sample/Mediatron.Sample that demonstrates:

  • Registering Mediatron
  • Sending a command that returns a value (CreateProductCommand)
  • Publishing an event to multiple handlers (ProductCreatedEvent)
  • Sending a command with no return value (DeleteProductCommand)
  • A logging pipeline behavior

Run it with:

cd sample/Mediatron.Sample
dotnet run

Running the Tests

The test suite uses xUnit, FluentAssertions, and NSubstitute.

dotnet test

Project Structure

Mediatron/
├── src/Mediatron/              # The library itself
│   ├── Abstractions/            # Interfaces: IRequest, INotification, IPipelineBehavior, etc.
│   ├── Core/                    # IMediator and its implementation (Mediator)
│   └── Extensions/              # AddMediatron() DI registration
├── sample/Mediatron.Sample/    # A runnable example console app
└── test/Mediatron.UnitTest/    # Unit tests

Documentation

For a deeper, guided walkthrough of every concept (requests, handlers, notifications, and pipeline behaviors), see the full documentation site built with DocFX in the documentation folder of this repository.

To build and view it locally:

dotnet tool install -g docfx
cd docfx
docfx docfx.json --serve

Then open your browser at http://localhost:8080.


Contributing

Contributions are welcome! Please see CONTRIBUTING.md and follow the Code of Conduct.

Security

If you discover a security issue, please read SECURITY.md for how to report it responsibly.

License

Mediatron 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
1.0.1 102 8/24/2026

initial release