CCMediator 1.1.0

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

CCMediator

A lightweight, dependency-injection-friendly mediator library for .NET 10, inspired by MediatR. Provides request/response and notification handling with minimal dependencies.

Warning This is an experimental test project used to explore how a mediator works. It is not intended for production use.

Packages

This repository ships three NuGet packages:

  • CCMediator (recommended) - meta package that depends on CCMediator.Core + CCMediator.DependencyInjection.
  • CCMediator.Core - core abstractions and mediator implementation (DI-container agnostic).
  • CCMediator.DependencyInjection - Microsoft.Extensions.DependencyInjection integration (service registration + optional scanning).

Features

  • Request/Response: Send requests and receive responses via strongly-typed handlers.
  • Notifications: Publish notifications to multiple handlers (sequential or parallel).
  • Pipeline behaviors: Add middleware around request handling.
  • Dependency Injection: Integration with Microsoft.Extensions.DependencyInjection.
  • Fast dispatch: Per-request-type cached dispatch using compiled delegates (no per-call reflection).
  • .NET 10: Modern C# and .NET features.

Getting Started

Installation

Recommended (includes DI integration):

dotnet add package CCMediator

Alternative packages:

# Core only (no DI helpers)
dotnet add package CCMediator.Core

# Microsoft.Extensions.DependencyInjection integration
dotnet add package CCMediator.DependencyInjection

Build / Pack

Pack all packages:

dotnet pack -c Release

The generated .nupkg files will be placed under each project folder, e.g.:

  • CCMediator/bin/Release/
  • CCMediator.Core/bin/Release/
  • CCMediator.DependencyInjection/bin/Release/

Publish to NuGet

Publishing runs in CI via .github/workflows/publish.yml using NuGet Trusted Publishing — no NuGet API key is stored as a secret. The workflow packs and pushes in dependency order (CCMediator.CoreCCMediator.DependencyInjectionCCMediator), using --skip-duplicate.

To release a new version:

  1. Bump <Version> in CCMediator/CCMediator.csproj, CCMediator.Core/CCMediator.Core.csproj, CCMediator.DependencyInjection/CCMediator.DependencyInjection.csproj, the CCMediator.Core / CCMediator.DependencyInjection versions in Directory.Packages.props, and the dependency versions in CCMediator/CCMediator.nuspec. Commit and merge.
  2. Publish a GitHub Release with tag vX.Y.Z matching that version (e.g. v1.2.0). This triggers the workflow automatically. It can also be run manually from the Actions tab (workflow_dispatch) by entering the version.

The workflow verifies the packed .nupkg version matches the release tag before pushing anything, so a forgotten version bump fails the run instead of publishing a stale package.

One-time setup (already done for this repo, documented for reference):

  1. On nuget.org → your username → Trusted Publishing → add a policy:
    • Repository Owner: ccarlsson
    • Repository: CCMediator
    • Workflow File: publish.yml
    • Environment: leave empty (the workflow doesn't use a GitHub environment)
  2. In the GitHub repo → Settings → Secrets and variables → Actions, add a secret NUGET_USER with your nuget.org profile username (ccarlsson) — not your email address.

Usage

The DI registration extension methods (AddCCMediator, AddCCMediatorWithScanning) are provided by the CCMediator.DependencyInjection package (and therefore also by the CCMediator meta package).

Register with DI (no scanning / explicit registration)

This is the default and avoids reflection-based assembly scanning.

using Microsoft.Extensions.DependencyInjection;
using CCMediator;

var services = new ServiceCollection();
services.AddCCMediator();

// Register handlers explicitly
services.AddTransient<IRequestHandler<Ping, string>, PingHandler>();
services.AddTransient<INotificationHandler<MyNotification>, MyNotificationHandler>();

var provider = services.BuildServiceProvider();
Register with DI (opt-in scanning)

If you prefer convenience over startup cost, you can explicitly enable scanning:

using Microsoft.Extensions.DependencyInjection;
using CCMediator;

var services = new ServiceCollection();
services.AddCCMediatorWithScanning(typeof(Startup).Assembly);
var provider = services.BuildServiceProvider();

Trade-offs:

  • Explicit registration: fastest startup, no reflection scan, most predictable.
  • Scanning: fewer registrations to write, but uses reflection (Assembly.GetTypes() and GetInterfaces()) during startup.
Define a request and handler
public record Ping(string Message) : IRequest<string>;

public class PingHandler : IRequestHandler<Ping, string>
{
    public Task<string> Handle(Ping request, CancellationToken cancellationToken)
        => Task.FromResult($"Pong: {request.Message}");
}
Send a request
var mediator = provider.GetRequiredService<IMediator>();
var response = await mediator.Send(new Ping("Hello"));
Define and publish a notification
public record MyNotification(string Info) : INotification;

public class MyNotificationHandler : INotificationHandler<MyNotification>
{
    public Task Handle(MyNotification notification, CancellationToken cancellationToken)
    {
        Console.WriteLine(notification.Info);
        return Task.CompletedTask;
    }
}

// Usage:
await mediator.Publish(new MyNotification("Something happened!"));

Configuration

You can configure publishing behavior via CCMediatorOptions:

using Microsoft.Extensions.DependencyInjection;
using CCMediator;

var services = new ServiceCollection();

services.AddCCMediator(options =>
{
    options.NotificationPublishMode = NotificationPublishMode.Sequential;
    options.SequentialPublishErrorHandling = NotificationPublishErrorHandling.ContinueAndAggregateExceptions;

    // For parallel mode:
    // options.NotificationPublishMode = NotificationPublishMode.Parallel;
    // options.AggregateExceptionsInParallel = true;
});

Pipeline behaviors

Register IPipelineBehavior<TRequest,TResponse> to wrap request handling. Execution order matches DI registration order.

services.AddTransient<IPipelineBehavior<Ping, string>, LoggingBehavior>();

public sealed class LoggingBehavior : IPipelineBehavior<Ping, string>
{
    public async Task<string> Handle(Ping request, Func<Task<string>> next, CancellationToken cancellationToken)
    {
        Console.WriteLine("Before");
        var result = await next();
        Console.WriteLine("After");
        return result;
    }
}

License

MIT License. See LICENSE.txt for details.

There are no supported framework assets in this 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.1.0 106 8/25/2026