FastMediator.Abstractions 1.0.0

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

FastMediator

A zero-reflection mediator for .NET powered by C# source generators. FastMediator generates all dispatcher and publisher code at compile time, so there is no runtime reflection, no dictionary lookups, and no dynamic dispatch — just direct, strongly-typed method calls.


Features

  • ⚡ Zero reflection — all routing is generated at compile time
  • 🔒 Compile-time safety — errors for duplicate or missing handlers are reported as build errors
  • 💉 DI-first — single AddFastMediator() call registers every handler and dispatcher
  • 📦 Lightweight — no external runtime dependencies beyond Microsoft.Extensions.DependencyInjection
  • 🔀 CQRS-ready — first-class support for Commands, Queries, and Notifications

How It Works

FastMediator uses an Incremental Source Generator (FastMediator.Generator) to inspect your project at build time. It:

  1. Discovers every class that implements IRequestHandler<TRequest, TResponse> or INotificationHandler<TNotification>.
  2. Emits compile-time diagnostics if handlers are duplicated or missing.
  3. Generates a CommandDispatcher, a QueryDispatcher, a NotificationPublisher, and an AddFastMediator() extension method — all inside the FastMediator.Generated namespace.

Because the routing code is generated as plain C# switch expressions, the JIT can inline and optimize it just like hand-written code.


Installation

Add the FastMediator NuGet package to your project:

<PackageReference Include="FastMediator" Version="1.0.0" />

Or via the .NET CLI:

dotnet add package FastMediator

Quick Start

1. Define a Command

A command performs a side-effectful operation and returns no meaningful value (Unit).

using FastMediator;

public record CreateOrderCommand(string Product) : ICommand;

2. Implement the Command Handler

using FastMediator;

public class CreateOrderHandler : IRequestHandler<CreateOrderCommand, Unit>
{
    public Task<Unit> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
    {
        Console.WriteLine($"Order created: {request.Product}");
        return Task.FromResult(Unit.Value);
    }
}

3. Define a Query

A query reads data and returns a typed result.

using FastMediator;

public record GetOrderQuery(int Id) : IQuery<string>;

4. Implement the Query Handler

using FastMediator;

public class GetOrderHandler : IRequestHandler<GetOrderQuery, string>
{
    public Task<string> Handle(GetOrderQuery request, CancellationToken cancellationToken)
    {
        return Task.FromResult($"Order #{request.Id}");
    }
}

5. Define a Notification

A notification broadcasts an event to multiple handlers.

using FastMediator;

public record OrderCreatedNotification(string Product) : INotification;

6. Implement a Notification Handler

using FastMediator;

public class OrderCreatedHandler : INotificationHandler<OrderCreatedNotification>
{
    public Task Handle(OrderCreatedNotification notification, CancellationToken cancellationToken)
    {
        Console.WriteLine($"Notification received: {notification.Product}");
        return Task.CompletedTask;
    }
}

7. Register and Use

Call AddFastMediator() once during startup. The source generator automatically includes every handler it discovers.

using FastMediator.Generated;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();

// Registers all handlers, CommandDispatcher, QueryDispatcher, and NotificationPublisher
services.AddFastMediator();

var provider = services.BuildServiceProvider();

var commandDispatcher = provider.GetRequiredService<CommandDispatcher>();
var queryDispatcher   = provider.GetRequiredService<QueryDispatcher>();
var publisher         = provider.GetRequiredService<NotificationPublisher>();

// Send a command
await commandDispatcher.Send(new CreateOrderCommand("Tile"));

// Execute a query
string result = await queryDispatcher.Query(new GetOrderQuery(123));
Console.WriteLine($"Query result: {result}");

// Publish a notification
await publisher.Publish(new OrderCreatedNotification("Tile"));

Core Concepts

Commands

A command represents an intention to change state. It implements ICommand, which in turn extends IRequest<Unit>. Commands produce no return value — the Unit type serves as a stand-in for void.

ICommand  ──extends──▶  IRequest<Unit>

Commands are dispatched through ICommandDispatcher.Send<TCommand>(command, cancellationToken).

Queries

A query retrieves data without modifying state. It implements IQuery<TResponse>, which extends IRequest<TResponse>.

IQuery<TResponse>  ──extends──▶  IRequest<TResponse>

Queries are dispatched through the generated QueryDispatcher.Query(query, cancellationToken) method, which is typed to the specific request/response pair.

Notifications

A notification broadcasts an event to zero or more handlers. It implements INotification. Multiple handlers for the same notification type are all invoked in sequence.

Notifications are published through INotificationPublisher.Publish<TNotification>(notification, cancellationToken).

Handlers

Interface Purpose
IRequestHandler<TRequest, TResponse> Handles both commands (TResponse = Unit) and queries
INotificationHandler<TNotification> Handles a specific notification type

Unit

Unit is a value type used as the return type for commands (equivalent to void). Access the singleton value via Unit.Value.


Dependency Injection

The generated AddFastMediator() extension method on IServiceCollection:

  • Registers every discovered handler as transient
  • Registers CommandDispatcher, QueryDispatcher, and NotificationPublisher as singletons
services.AddFastMediator();

All three dispatchers are available directly from the DI container:

var commandDispatcher = provider.GetRequiredService<CommandDispatcher>();
var queryDispatcher   = provider.GetRequiredService<QueryDispatcher>();
var publisher         = provider.GetRequiredService<NotificationPublisher>();

Compile-Time Diagnostics

The source generator validates your handler registrations at build time and reports the following errors:

Code Description
FM001 Multiple handlers found for the same command type
FM002 Multiple handlers found for the same query type
FM003 No handler found for a notification type

These errors appear as standard MSBuild/IDE errors — you will see them in the Error List before your application ever runs.


Generated Code

At build time, the generator emits a file called FastMediator.Generated.g.cs inside the FastMediator.Generated namespace. It contains:

  • CommandDispatcher — implements ICommandDispatcher, routes each command type to its handler via a switch expression.
  • QueryDispatcher — implements IQueryDispatcherMarker, exposes a strongly-typed Query(...) method per query type.
  • NotificationPublisher — implements INotificationPublisher, fans out each notification to all registered handlers via a switch statement.
  • FastMediatorServiceCollectionExtensions — provides the AddFastMediator() extension method.

Example (abbreviated) for the sample project:

// Auto-generated — do not edit
namespace FastMediator.Generated
{
    public sealed class CommandDispatcher : ICommandDispatcher
    {
        private readonly CreateOrderHandler _createOrderHandler;

        public CommandDispatcher(CreateOrderHandler createOrderHandler)
            => _createOrderHandler = createOrderHandler;

        public Task Send<TCommand>(TCommand command, CancellationToken ct = default)
            where TCommand : ICommand
        {
            return command switch
            {
                CreateOrderCommand c => _createOrderHandler.Handle(c, ct),
                _ => throw new InvalidOperationException($"No handler found for command type '{typeof(TCommand).Name}'")
            };
        }
    }

    public sealed class QueryDispatcher : IQueryDispatcherMarker
    {
        private readonly GetOrderHandler _getOrderHandler;

        public QueryDispatcher(GetOrderHandler getOrderHandler)
            => _getOrderHandler = getOrderHandler;

        public Task<string> Query(GetOrderQuery query, CancellationToken ct = default)
            => _getOrderHandler.Handle(query, ct);
    }

    public sealed class NotificationPublisher : INotificationPublisher
    {
        private readonly OrderCreatedHandler _orderCreatedHandler;

        public NotificationPublisher(OrderCreatedHandler orderCreatedHandler)
            => _orderCreatedHandler = orderCreatedHandler;

        public async Task Publish<TNotification>(TNotification notification, CancellationToken ct = default)
            where TNotification : INotification
        {
            switch (notification)
            {
                case OrderCreatedNotification n:
                    await _orderCreatedHandler.Handle(n, ct);
                    break;
                default:
                    throw new InvalidOperationException($"No handlers found for notification type '{typeof(TNotification).Name}'");
            }
        }
    }
}

Project Structure

FastMediator/
├── FastMediator.Abstractions/        # Public interfaces and value types
│   ├── IRequest.cs                   # Base request interface
│   ├── ICommand.cs                   # Command marker interface
│   ├── IQuery.cs                     # Query interface
│   ├── IRequestHandler.cs            # Handler interface
│   ├── INotification.cs              # Notification marker interface
│   ├── INotificationHandler.cs       # Notification handler interface
│   ├── ICommandDispatcher.cs         # Command dispatcher interface
│   ├── INotificationPublisher.cs     # Notification publisher interface
│   ├── IQueryDispatcherMarker.cs     # Query dispatcher marker interface
│   └── Unit.cs                       # Unit value type
│
├── FastMediator.Generator/           # Roslyn incremental source generator
│   └── MediatorGenerator.cs          # Discovers handlers, validates, and emits code
│
├── FastMediator/                     # Main NuGet package project
│   └── FastMediator.csproj
│
├── FastMediator.Sample/              # Example console application
│   ├── CreateOrderCommand.cs
│   ├── CreateOrderHandler.cs
│   ├── GetOrderQuery.cs
│   ├── GetOrderHandler.cs
│   ├── OrderCreatedNotification.cs
│   ├── OrderCreatedHandler.cs
│   └── Program.cs
│
└── FastMediator.Tests/               # Unit tests (xUnit)
    ├── CommandDispatcherTests.cs
    ├── QueryDispatcherTests.cs
    └── NotificationPublisherTests.cs

License

This project is open source. See the repository for license details.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  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 was computed.  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. 
.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.
  • .NETStandard 2.0

    • No dependencies.

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.0 126 3/21/2026