CCMediator 1.1.0
dotnet add package CCMediator --version 1.1.0
NuGet\Install-Package CCMediator -Version 1.1.0
<PackageReference Include="CCMediator" Version="1.1.0" />
<PackageVersion Include="CCMediator" Version="1.1.0" />
<PackageReference Include="CCMediator" />
paket add CCMediator --version 1.1.0
#r "nuget: CCMediator, 1.1.0"
#:package CCMediator@1.1.0
#addin nuget:?package=CCMediator&version=1.1.0
#tool nuget:?package=CCMediator&version=1.1.0
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 onCCMediator.Core+CCMediator.DependencyInjection.CCMediator.Core- core abstractions and mediator implementation (DI-container agnostic).CCMediator.DependencyInjection-Microsoft.Extensions.DependencyInjectionintegration (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.Core → CCMediator.DependencyInjection → CCMediator), using --skip-duplicate.
To release a new version:
- Bump
<Version>inCCMediator/CCMediator.csproj,CCMediator.Core/CCMediator.Core.csproj,CCMediator.DependencyInjection/CCMediator.DependencyInjection.csproj, theCCMediator.Core/CCMediator.DependencyInjectionversions inDirectory.Packages.props, and the dependency versions inCCMediator/CCMediator.nuspec. Commit and merge. - Publish a GitHub Release with tag
vX.Y.Zmatching 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):
- 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)
- Repository Owner:
- In the GitHub repo → Settings → Secrets and variables → Actions, add a secret
NUGET_USERwith your nuget.org profile username (ccarlsson) — not your email address.
Usage
The DI registration extension methods (
AddCCMediator,AddCCMediatorWithScanning) are provided by theCCMediator.DependencyInjectionpackage (and therefore also by theCCMediatormeta 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()andGetInterfaces()) 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.
Learn more about Target Frameworks and .NET Standard.
-
- CCMediator.Core (>= 1.1.0)
- CCMediator.DependencyInjection (>= 1.1.0)
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 |