PicoMediator.DI 2026.1.2

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

PicoMediator

Compile-time request/notification dispatch for PicoDI. Zero reflection, AOT-first.

Quick Start

dotnet add package PicoMediator
using PicoDI;
using PicoMediator;
using PicoMediator.Abs;

var container = new SvcContainer();

// Register handlers
container.Register<IRequestHandler<Ping, string>, PingHandler>(SvcLifetime.Transient);
container.RegisterSingle<INotificationHandler<OrderCreated>>(new OrderCreatedEmailHandler());

// Register mediator
container.AddPicoMediator();
container.Build();

await using var scope = container.CreateScope();
var mediator = scope.GetService<IMediator>();

// Send: 1:1 request → response
var result = await mediator.Send<Ping, string>(new Ping());

// Publish: 1:N notification → all subscribers
await mediator.Publish(new OrderCreated(Guid.NewGuid(), "book"));

Core Concepts

Interaction Patterns

PicoMediator follows the ZeroMQ-inspired principle: interaction patterns are atomic primitives encoded by the type system.

Pattern ZeroMQ C# Type Cardinality Response
Request REQ/REP IRequest<TResponse> 1:1 Yes
Notification PUB/SUB INotification 1:N No

No ICommand/IQuery split — define your own via interface inheritance if needed:

public interface ICommand<T> : IRequest<T> { }
public interface IQuery<T> : IRequest<T> { }

No IStreamRequest — wrap IAsyncEnumerable<T> in the response:

public record ExportUsers : IRequest<ExportUsersResponse>;
public record ExportUsersResponse(IAsyncEnumerable<User> Users);

Void Commands

Use VoidResult (from PicoDI.Abs) for fire-and-forget commands:

public record DeleteOrder(Guid Id) : IRequest<VoidResult>;

public class DeleteOrderHandler : IRequestHandler<DeleteOrder, VoidResult>
{
    public async ValueTask<VoidResult> Handle(DeleteOrder r, CancellationToken ct)
    {
        await DeleteAsync(r.Id, ct);
        return default;
    }
}

Publisher/Subscriber Semantics

Publish follows ZeroMQ PUB/SUB semantics:

  • Publisher does not know subscribers
  • No return value (protocol forbids it)
  • No subscribers → silent drop (not an error)
  • Multiple subscribers → each receives the notification
// 2 subscribers
container.RegisterSingle<INotificationHandler<OrderCreated>>(new EmailHandler());
container.RegisterSingle<INotificationHandler<OrderCreated>>(new AuditHandler());

await mediator.Publish(new OrderCreated(id, item));
// → EmailHandler.Handle() called
// → AuditHandler.Handle() called

Registration

Handlers

Handlers are standard PicoDI registrations:

// Factory-based
container.RegisterTransient<IRequestHandler<Ping, string>>(_ => new PingHandler());
container.RegisterScoped<IRequestHandler<CreateOrder, OrderResult>>(_ => new CreateOrderHandler());

// Instance
container.RegisterSingle<INotificationHandler<OrderCreated>>(new EmailHandler());

// Type-based (requires PicoDI.Gen source generator)
container.Register<IRequestHandler<Ping, string>, PingHandler>(SvcLifetime.Transient);

Mediator

One line — registers IMediator as Scoped:

container.AddPicoMediator();

Narrow Ports

Depend on the narrowest interface for your component:

// Only sends requests
public sealed class OrderController(ISender sender) { ... }

// Only publishes notifications
public sealed class EventSource(IPublisher publisher) { ... }

// Orchestration — needs both
public sealed class CheckoutService(IMediator mediator) { ... }

Pipeline Behaviors (via PicoAop)

PicoMediator does NOT define its own pipeline abstraction. Use PicoAop interceptors instead:

// Mediator-level — applies to all Send/Publish calls
container.Register<IMediator, Mediator>(SvcLifetime.Scoped)
    .InterceptBy<MetricsInterceptor>();

// Handler-level — applies to a specific request type
container.Register<IRequestHandler<CreateOrder, OrderResult>, CreateOrderHandler>(SvcLifetime.Transient)
    .InterceptBy<LoggingInterceptor>()
    .InterceptBy<ValidationInterceptor>()
    .InterceptBy<TransactionInterceptor>();

// Decorator chain (onion model):
// Transaction → Validation → Logging → Handler

Source Generator (PicoMediator.Gen)

Add PicoMediator.Gen as an analyzer:

<PackageReference Include="PicoMediator.Gen" PrivateAssets="all" />

The generator scans IRequestHandler<T, T> implementations and emits:

  • GeneratedMediatorDispatch.Send() — switch-based dispatch with Unsafe.As cast (zero allocation)
  • Runtime fallbackscope.GetService<T>() for handlers not in the switch table

Without the generator, Mediator.Send() still works via the runtime GetService fallback.

Error Handling

Scenario Behavior
Send — no handler registered InvalidOperationException
Send — handler throws Exception propagates to caller
Publish — no subscribers Silent (PUB/SUB semantics)
Publish — one handler throws Exception propagates to caller
Publish — multiple handlers fail AggregateException

Packages

Package Description
PicoMediator.Abs IRequest<T>, INotification, IRequestHandler<T, T>, INotificationHandler<T>, ISender, IPublisher, IMediator
PicoMediator Mediator(ISvcScope) runtime
PicoMediator.Gen Source generator — switch dispatch
PicoMediator.DI container.AddPicoMediator()

← Back to PicoHex

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
2026.1.2 60 6/10/2026
2026.1.1 90 6/4/2026