SwiftMediator 2026.4.3

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

SwiftMediator

High-performance, source-generated mediator pattern for .NET — a drop-in replacement for MediatR with compile-time dispatch, zero-allocation fast paths, and full AOT/Trim compatibility.

CI NuGet License: MIT

Why SwiftMediator?

MediatR SwiftMediator
Dispatch Runtime reflection + Dictionary<Type> Compile-time switch (source-generated)
Return type Task<T> ValueTask<T> (zero alloc for sync)
No-behavior path Allocates pipeline Fast-path — direct call, zero overhead
AOT / Trim Not compatible Fully compatible (net8.0+)
Error detection Runtime exceptions Compile-time diagnostics
Frameworks net8.0, netstandard2.0 net10.0, net8.0, netstandard2.0, net462
License Paid license key required MIT — free forever

Full MediatR feature parity — 20/20 features including polymorphic notifications.

Installation

dotnet add package SwiftMediator

For shared/API projects that only need marker interfaces:

dotnet add package SwiftMediator.Contracts

Quick Start

1. Define a Request and Handler

using SwiftMediator.Core;

public record PongResponse(string Reply);

public class PingRequest : IRequest<PongResponse>
{
    public string Message { get; init; } = "";
}

public class PingHandler : IRequestHandler<PingRequest, PongResponse>
{
    public ValueTask<PongResponse> Handle(PingRequest request, CancellationToken ct)
    {
        return new ValueTask<PongResponse>(new PongResponse($"Pong: {request.Message}"));
    }
}

2. Register and Use

var services = new ServiceCollection();

services.AddSwiftMediator(cfg =>
{
    cfg.RegisterServicesFromAssemblyContaining<Program>();
});

var provider = services.BuildServiceProvider();
var mediator = provider.GetRequiredService<IMediator>();

var response = await mediator.SendAsync<PingRequest, PongResponse>(
    new PingRequest { Message = "Hello!" });
// response.Reply == "Pong: Hello!"

Examples

Sample Description
BasicUsage Request/response, void commands, notifications, streaming, dynamic dispatch
CqrsWithValidation CQRS pattern with commands, queries, validation pipeline, domain events
AdvancedPipeline Full pipeline behaviors, exception handling, polymorphic notifications, stream pipeline, custom publisher

Features

Void (Unit) Requests

public class DeleteUserCommand : IRequest
{
    public int UserId { get; init; }
}

public class DeleteUserHandler : IRequestHandler<DeleteUserCommand, Unit>
{
    public ValueTask<Unit> Handle(DeleteUserCommand request, CancellationToken ct)
    {
        // perform deletion
        return new ValueTask<Unit>(Unit.Value);
    }
}

// Convenience — no need to specify Unit:
await mediator.SendAsync(new DeleteUserCommand { UserId = 42 });

Notifications (Pub/Sub)

public class OrderCreatedEvent : INotification
{
    public int OrderId { get; init; }
}

public class EmailHandler : INotificationHandler<OrderCreatedEvent>
{
    public ValueTask Handle(OrderCreatedEvent notification, CancellationToken ct)
    {
        // send email
        return default;
    }
}

// Publish strategies:
await mediator.PublishAsync(evt, PublishStrategy.Sequential);   // one by one (default)
await mediator.PublishAsync(evt, PublishStrategy.Parallel);     // Task.WhenAll
await mediator.PublishAsync(evt, PublishStrategy.FireAndForget); // fire & forget

Polymorphic Notifications

Handlers registered for a base type/interface are invoked for all derived types:

public interface IOrderEvent : INotification { }
public class OrderConfirmedEvent : IOrderEvent { }
public class OrderCancelledEvent : IOrderEvent { }

// Runs for ALL IOrderEvent types:
public class AuditHandler : INotificationHandler<IOrderEvent> { ... }

// Runs only for OrderConfirmedEvent:
public class ConfirmedHandler : INotificationHandler<OrderConfirmedEvent> { ... }

Streaming (IAsyncEnumerable)

public class SearchQuery : IStreamRequest<SearchResult>
{
    public string Term { get; init; } = "";
}

public class SearchHandler : IStreamRequestHandler<SearchQuery, SearchResult>
{
    public async IAsyncEnumerable<SearchResult> Handle(
        SearchQuery request, [EnumeratorCancellation] CancellationToken ct)
    {
        await foreach (var item in db.SearchAsync(request.Term))
            yield return item;
    }
}

await foreach (var result in mediator.CreateStream<SearchQuery, SearchResult>(query))
    Console.WriteLine(result);

Pipeline Behaviors (Middleware)

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

Fast-path: When no behaviors are registered, the handler is called directly — zero overhead.

Pre/Post Processors

public class ValidationPreProcessor<TRequest> : IRequestPreProcessor<TRequest>
    where TRequest : notnull
{
    public ValueTask Process(TRequest request, CancellationToken ct) { /* validate */ return default; }
}

public class AuditPostProcessor<TReq, TRes> : IRequestPostProcessor<TReq, TRes>
    where TReq : notnull
{
    public ValueTask Process(TReq request, TRes response, CancellationToken ct) { /* audit */ return default; }
}

Execution order: PreProcessor → Behavior(s) → Handler → PostProcessor

Exception Pipeline

// Actions — observe only (logging, metrics), cannot suppress
public class MetricsAction<TReq> : IRequestExceptionAction<TReq, Exception>
    where TReq : notnull
{
    public ValueTask Execute(TReq request, Exception ex, CancellationToken ct)
    {
        // record metrics
        return default;
    }
}

// Handlers — can suppress exception and return fallback
public class FallbackHandler : IRequestExceptionHandler<MyRequest, MyResponse, InvalidOperationException>
{
    public ValueTask Handle(MyRequest req, InvalidOperationException ex,
        RequestExceptionHandlerState<MyResponse> state, CancellationToken ct)
    {
        state.SetHandled(new MyResponse { /* fallback */ });
        return default;
    }
}

Order: Actions run first (always), then Handlers (can suppress via SetHandled()).

Stream Pipeline Behaviors

public class StreamLogging<TReq, TRes> : IStreamPipelineBehavior<TReq, TRes>
    where TReq : IStreamRequest<TRes>
{
    public async IAsyncEnumerable<TRes> Handle(
        TReq request, StreamHandlerDelegate<TRes> next,
        [EnumeratorCancellation] CancellationToken ct)
    {
        Console.WriteLine("Stream starting");
        await foreach (var item in next())
            yield return item;
        Console.WriteLine("Stream completed");
    }
}

Custom Notification Publisher

public class BatchPublisher : INotificationPublisher
{
    public async ValueTask Publish(
        IEnumerable<NotificationHandlerExecutor> executors,
        INotification notification, CancellationToken ct)
    {
        foreach (var executor in executors)
            await executor.HandlerCallback(notification, ct);
    }
}

Built-in: ForeachAwaitPublisher, TaskWhenAllPublisher, FireAndForgetPublisher.

ISender / IPublisher Segregation

// Depend on the narrowest interface:
public class MyService(ISender sender) { }    // can only send requests
public class MyPub(IPublisher publisher) { }  // can only publish notifications

All three (IMediator, ISender, IPublisher) resolve to the same instance.

DI Configuration

Fluent API

services.AddSwiftMediator(cfg =>
{
    // Lifetime
    cfg.Lifetime = HandlerLifetime.Scoped;           // handlers (default: Transient)
    cfg.MediatorLifetime = HandlerLifetime.Singleton; // mediator (default: Scoped)

    // Assembly scanning — auto-discovers behaviors, processors, exception handlers
    cfg.RegisterServicesFromAssemblyContaining<Program>();

    // Or register explicitly:
    cfg.AddOpenBehavior(typeof(LoggingBehavior<,>))
       .AddOpenBehavior(typeof(ValidationBehavior<,>))
       .AddRequestPreProcessor<AuditPreProcessor>()
       .AddRequestPostProcessor<CachePostProcessor>()
       .AddExceptionHandler<FallbackExceptionHandler>()
       .AddExceptionAction<MetricsAction>()
       .AddStreamBehavior<StreamLoggingBehavior>()
       .SetNotificationPublisher<TaskWhenAllPublisher>();
});

Assembly Scanning Discovers

  • IPipelineBehavior<,> / IStreamPipelineBehavior<,>
  • IRequestPreProcessor<> / IRequestPostProcessor<,>
  • IRequestExceptionHandler<,,> / IRequestExceptionAction<,>

Handlers (IRequestHandler, INotificationHandler, IStreamRequestHandler) are discovered at compile time by the source generator — not by assembly scanning.

Compile-Time Diagnostics

ID Severity Description
SWIFT001 Error Duplicate request handler
SWIFT002 Error Duplicate stream handler
SWIFT003 Warning No handlers found
SWIFT004 Info Open generic handler registered

Supported Frameworks

Package Targets
SwiftMediator net10.0, net8.0, netstandard2.0, net462
SwiftMediator.Contracts netstandard2.0

AOT and trim compatible on net8.0+.

Feature List

  • Request/Response (IRequest<T>IRequestHandler<T, R>)
  • Void requests (IRequestUnit)
  • Notifications (INotificationINotificationHandler<T>)
  • Polymorphic notifications (base type handlers invoked for derived types)
  • Streaming (IStreamRequest<T>IAsyncEnumerable<T>)
  • Pipeline behaviors (IPipelineBehavior<T, R>)
  • Stream pipeline behaviors (IStreamPipelineBehavior<T, R>)
  • Pre/Post processors
  • Exception handlers (suppress + fallback)
  • Exception actions (observe only)
  • Custom notification publisher (INotificationPublisher)
  • ISender / IPublisher interface segregation
  • Fluent DI configuration
  • Assembly scanning
  • Open generic handler support
  • Polymorphic request dispatch
  • Dynamic dispatch (SendAsync(object))
  • Handler lifetime configuration (Transient / Scoped / Singleton)
  • Compile-time diagnostics
  • Multi-framework support (net10.0, net8.0, netstandard2.0, net462)

Migrating from MediatR

SwiftMediator uses the same API patterns as MediatR — migration is straightforward:

MediatR SwiftMediator
services.AddMediatR(cfg => ...) services.AddSwiftMediator(cfg => ...)
cfg.RegisterServicesFromAssemblyContaining<T>() Same
cfg.AddOpenBehavior(typeof(T<,>)) Same
cfg.AddRequestPreProcessor<T>() Same
cfg.AddRequestPostProcessor<T>() Same
cfg.AddStreamBehavior<T>() Same
IRequestHandler<TReq, TRes> returns Task<T> Returns ValueTask<T>
cfg.LicenseKey = "..." Not needed — MIT licensed

Note: MediatR now requires a paid license key. SwiftMediator is and will remain free and open source under the MIT license.

Support

If you find SwiftMediator useful, consider buying me a coffee:

Buy Me a Coffee

License

MIT

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 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 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. 
.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 is compatible.  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.

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
2026.4.3 73 4/13/2026