AxisCore.Mediator 1.0.1

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

AxisCore.Mediator

CI/CD NuGet License: MIT

A high-performance, production-ready .NET library implementing the Mediator pattern. AxisCore.Mediator provides a simple, ergonomic API similar to MediatR while delivering superior performance through minimal allocations, ValueTask optimization, and intelligent handler caching.

Features

  • High Performance: ValueTask-based, zero-allocation hot path with compiled delegate caching
  • Multi-Targeting: Supports .NET 9, .NET 8, and .NET 6
  • Simple API: Clean, intuitive interface similar to MediatR
  • Pipeline Behaviors: Middleware-style request processing
  • DI First: Seamless integration with Microsoft.Extensions.DependencyInjection
  • Streaming Support: Built-in support for IAsyncEnumerable streaming responses
  • Flexible Publishing: Multiple notification publishing strategies (parallel, sequential)
  • Comprehensive Testing: Extensive unit and integration test coverage
  • Production Ready: Thread-safe, cancellation-aware, with robust error handling

Installation

dotnet add package AxisCore.Mediator

Quick Start

1. Define a Request and Handler

using AxisCore.Mediator;

// Define a request
public class GreetingRequest : IRequest<string>
{
    public string Name { get; set; }
}

// Define a handler
public class GreetingRequestHandler : IRequestHandler<GreetingRequest, string>
{
    public ValueTask<string> Handle(GreetingRequest request, CancellationToken cancellationToken)
    {
        return new ValueTask<string>($"Hello, {request.Name}!");
    }
}

2. Register with DI

using Microsoft.Extensions.DependencyInjection;
using AxisCore.Mediator.DependencyInjection;

var services = new ServiceCollection();

// Auto-scan and register all handlers from the calling assembly
services.AddMediatorFromAssembly();

// Or scan specific assemblies
services.AddMediator(new[] { typeof(Program).Assembly });

var provider = services.BuildServiceProvider();

3. Send Requests

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

var response = await mediator.Send(new GreetingRequest { Name = "World" });
// Output: "Hello, World!"

Core Concepts

Requests and Handlers

Requests represent actions or queries. Handlers contain the logic to process them.

// Request with response
public class CreateOrderCommand : IRequest<OrderResult>
{
    public string CustomerId { get; set; }
    public decimal Amount { get; set; }
}

public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand, OrderResult>
{
    public ValueTask<OrderResult> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
    {
        // Business logic here
        return new ValueTask<OrderResult>(new OrderResult { OrderId = Guid.NewGuid() });
    }
}

// Usage
var result = await mediator.Send(new CreateOrderCommand { CustomerId = "123", Amount = 99.99m });

Notifications

Notifications are published to multiple handlers (pub/sub pattern).

// Define notification
public class OrderCreatedNotification : INotification
{
    public string OrderId { get; set; }
}

// Define handlers (multiple handlers can handle the same notification)
public class SendEmailHandler : INotificationHandler<OrderCreatedNotification>
{
    public ValueTask Handle(OrderCreatedNotification notification, CancellationToken cancellationToken)
    {
        // Send email logic
        return ValueTask.CompletedTask;
    }
}

public class UpdateInventoryHandler : INotificationHandler<OrderCreatedNotification>
{
    public ValueTask Handle(OrderCreatedNotification notification, CancellationToken cancellationToken)
    {
        // Update inventory logic
        return ValueTask.CompletedTask;
    }
}

// Usage
await mediator.Publish(new OrderCreatedNotification { OrderId = "ORD-123" });

Pipeline Behaviors

Pipeline behaviors wrap around request handlers, enabling cross-cutting concerns like logging, validation, and performance monitoring.

public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger;

    public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
    {
        _logger = logger;
    }

    public async ValueTask<TResponse> Handle(
        TRequest request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Handling {RequestName}", typeof(TRequest).Name);
        var response = await next();
        _logger.LogInformation("Handled {RequestName}", typeof(TRequest).Name);
        return response;
    }
}

// Register
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));

Streaming Responses

For scenarios requiring streaming data:

public class GetLogsRequest : IStreamRequest<LogEntry>
{
    public DateTime FromDate { get; set; }
}

public class GetLogsHandler : IStreamRequestHandler<GetLogsRequest, LogEntry>
{
    public async IAsyncEnumerable<LogEntry> Handle(
        GetLogsRequest request,
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        await foreach (var log in FetchLogsAsync(request.FromDate, cancellationToken))
        {
            yield return log;
        }
    }
}

// Usage
await foreach (var log in mediator.CreateStream(new GetLogsRequest { FromDate = DateTime.UtcNow.AddDays(-7) }))
{
    Console.WriteLine(log);
}

Configuration

Publishing Strategies

Control how notifications are published to multiple handlers:

services.AddMediator(options =>
{
    // Publish to all handlers in parallel (default)
    options.NotificationPublisherStrategy = NotificationPublisherStrategy.PublishParallel;

    // Or publish sequentially
    // options.NotificationPublisherStrategy = NotificationPublisherStrategy.PublishSequential;

    // Or stop on first exception
    // options.NotificationPublisherStrategy = NotificationPublisherStrategy.PublishSequentialStopOnException;
});

Service Lifetimes

Specify handler lifetimes:

// Transient (default)
services.AddMediatorFromAssembly(lifetime: ServiceLifetime.Transient);

// Scoped
services.AddMediatorFromAssembly(lifetime: ServiceLifetime.Scoped);

// Or manually register
services.AddRequestHandler<MyRequest, MyResponse, MyHandler>(ServiceLifetime.Scoped);

Built-in Behaviors

Logging Behavior

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));

Performance Monitoring

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(PerformanceBehavior<,>));

Validation

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));

Performance

AxisCore.Mediator is designed for high-performance scenarios:

  • ValueTask: Reduces allocations for synchronous or cached operations
  • Handler Caching: Compiled delegates cached for fast resolution
  • Minimal Allocations: Zero-allocation hot path for simple requests
  • Concurrent Safe: Thread-safe handler resolution and caching

Benchmarks

Method Mean Error Allocated
AxisCore_Send 45.2 ns 0.4 ns 0 B
MediatR_Send 78.3 ns 1.2 ns 64 B
AxisCore_Publish 123.1 ns 2.1 ns 0 B
MediatR_Publish 198.4 ns 3.4 ns 128 B

Run your own benchmarks:

dotnet run --project benchmarks/AxisCore.Mediator.Benchmarks -c Release

Migration from MediatR

See MIGRATION.md for a detailed migration guide.

Key Differences:

  • Handlers return ValueTask<T> instead of Task<T>
  • Some MediatR-specific features may differ (see migration guide)

Documentation

Examples

See the samples directory for complete examples:

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.

License

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

Support

Acknowledgments

Inspired by MediatR by Jimmy Bogard. This library aims to provide a similar developer experience with enhanced performance characteristics.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  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 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
1.0.2 384 11/21/2025
1.0.1 416 11/20/2025
1.0.0 412 11/19/2025