CleanArch.DevKit.Mediator
1.1.1
dotnet add package CleanArch.DevKit.Mediator --version 1.1.1
NuGet\Install-Package CleanArch.DevKit.Mediator -Version 1.1.1
<PackageReference Include="CleanArch.DevKit.Mediator" Version="1.1.1" />
<PackageVersion Include="CleanArch.DevKit.Mediator" Version="1.1.1" />
<PackageReference Include="CleanArch.DevKit.Mediator" />
paket add CleanArch.DevKit.Mediator --version 1.1.1
#r "nuget: CleanArch.DevKit.Mediator, 1.1.1"
#:package CleanArch.DevKit.Mediator@1.1.1
#addin nuget:?package=CleanArch.DevKit.Mediator&version=1.1.1
#tool nuget:?package=CleanArch.DevKit.Mediator&version=1.1.1
CleanArch.DevKit.Mediator
Médiateur générant son code à la compilation pour .NET 10. Découverte des handlers via Roslyn, dispatch zéro-réflexion, aucune scan d'assembly au runtime.
Rôle
Découple l'application des handlers de commandes/queries/événements via une interface IMediator. Contrairement aux médiateurs classiques, les handlers sont détectés à la compilation par un générateur de source : la classe Mediator et la méthode AddMediator() sont émises avec des appels typés directs — pas de MakeGenericMethod, pas de cache de delegates, pas de réflexion sur le chemin chaud.
Installation
dotnet add package CleanArch.DevKit.Mediator
Le générateur Roslyn est embarqué dans le package : aucun package séparé à installer.
Fonctionnalités
- Déclarer une classe
partial Mediatorpour activer la génération - Envoyer une requête avec réponse (
IRequest<TResponse>) - Envoyer une commande fire-and-forget (
IRequest) - Publier une notification à plusieurs handlers (
INotification) - Consommer un flux de réponses (
IStreamRequest<TResponse>) - Ajouter un comportement de pipeline (
IPipelineBehavior<,>) - Choisir la stratégie de publication des notifications (séquentielle ou parallèle)
- Diagnostics Roslyn à la compilation (
MED001–MED003)
Déclarer la classe Mediator
Ajouter un fichier qui contient la classe partielle vide. Le générateur la complète :
namespace MyApp;
public partial class Mediator { }
Puis enregistrer dans le conteneur DI :
services.AddMediator();
La classe doit être dans un namespace (pas en
global) et dans le même projet que les handlers — le générateur ne scanne pas les assemblies référencées.
Envoyer une requête avec réponse
public sealed record GetUser(int Id) : IRequest<User>;
public sealed class GetUserHandler(IUserRepository repo) : IRequestHandler<GetUser, User>
{
public Task<User> Handle(GetUser query, CancellationToken ct)
=> repo.FindAsync(query.Id, ct);
}
// Appel
var user = await mediator.Send(new GetUser(42), ct);
Envoyer une commande fire-and-forget
IRequest (sans paramètre de type) est un raccourci pour IRequest<Unit> — utile quand la commande ne renvoie rien :
public sealed record DeleteUser(int Id) : IRequest;
public sealed class DeleteUserHandler(IUserRepository repo) : IRequestHandler<DeleteUser>
{
public async Task<Unit> Handle(DeleteUser cmd, CancellationToken ct)
{
await repo.DeleteAsync(cmd.Id, ct);
return Unit.Value;
}
}
await mediator.Send(new DeleteUser(42), ct);
Unit est un readonly record struct qui matérialise l'absence de valeur.
Publier une notification
Une notification peut être traitée par zéro, un ou plusieurs handlers :
public sealed record UserCreated(int Id) : INotification;
public sealed class SendWelcomeEmail : INotificationHandler<UserCreated>
{
public Task Handle(UserCreated evt, CancellationToken ct) => /* ... */;
}
public sealed class UpdateAuditLog : INotificationHandler<UserCreated>
{
public Task Handle(UserCreated evt, CancellationToken ct) => /* ... */;
}
await mediator.Publish(new UserCreated(42), ct);
Consommer un flux de réponses
public sealed record GetLogs(DateTime Since) : IStreamRequest<LogEntry>;
public sealed class GetLogsHandler(ILogRepository repo) : IStreamRequestHandler<GetLogs, LogEntry>
{
public async IAsyncEnumerable<LogEntry> Handle(
GetLogs query,
[EnumeratorCancellation] CancellationToken ct)
{
await foreach (var entry in repo.StreamAsync(query.Since, ct))
yield return entry;
}
}
// Consommation
await foreach (var entry in mediator.CreateStream(new GetLogs(start), ct))
Console.WriteLine(entry);
Annoter le
CancellationTokendu handler avec[EnumeratorCancellation]est nécessaire pour queWithCancellation(...)côté appelant fonctionne.
Ajouter un comportement de pipeline
Un IPipelineBehavior<TRequest, TResponse> enveloppe l'exécution du handler — utile pour la journalisation, la validation, le retry, etc. Les behaviors s'exécutent dans l'ordre d'enregistrement, le premier inscrit étant le plus externe :
public sealed class TimingBehavior<TRequest, TResponse>(ILogger<TimingBehavior<TRequest, TResponse>> logger)
: IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken ct)
{
var sw = Stopwatch.StartNew();
var response = await next(ct);
logger.LogInformation("{Request} took {Ms}ms", typeof(TRequest).Name, sw.ElapsedMilliseconds);
return response;
}
}
// Enregistrement (générique ouvert)
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(TimingBehavior<,>));
Pour court-circuiter le handler, ne pas appeler next(ct) et retourner directement une réponse.
Le package
CleanArch.DevKit.Mediator.BehaviorsfournitLoggingBehavior,PerformanceBehavioretUnhandledExceptionBehaviorprêts à l'emploi.
Choisir la stratégie de publication
Quand plusieurs handlers traitent la même notification, contrôler leur invocation :
services.AddMediator(options =>
{
// Séquentiel (défaut) : un handler après l'autre dans l'ordre d'enregistrement.
// La première exception arrête la chaîne.
options.NotificationPublisherStrategy = NotificationPublisherStrategy.Sequential;
// Parallèle : tous les handlers via Task.WhenAll.
// Toutes les exceptions sont agrégées dans une AggregateException.
options.NotificationPublisherStrategy = NotificationPublisherStrategy.Parallel;
});
Diagnostics à la compilation
| Code | Sévérité | Condition |
|---|---|---|
MED001 |
Error | Un IRequest<T> n'a aucun handler |
MED002 |
Error | Plusieurs handlers pour le même IRequest<T> |
MED003 |
Error | Aucune public partial class Mediator { } détectée dans le projet |
Les exceptions runtime InvalidMessageException et MultipleHandlersException servent de filet de sécurité si le diagnostic est ignoré.
Limitation connue
Tous les handlers et la déclaration partial class Mediator doivent vivre dans le même projet. Les types des assemblies référencées ne sont pas scannés. Pour une solution multi-projets, agréger les handlers dans le projet qui déclare la classe partielle.
Migration depuis MediatR
Les signatures sont volontairement compatibles :
| Avant (MediatR) | Après (CleanArch.DevKit.Mediator) |
|---|---|
using MediatR; |
using CleanArch.DevKit.Mediator; |
services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(...)) |
services.AddMediator() |
| (aucune classe à déclarer) | Ajouter public partial class Mediator { } |
IRequestPreProcessor, IRequestPostProcessor |
Réécrire en IPipelineBehavior<,> |
IRequest<T>, IRequest, INotification, IStreamRequest<T>, IPipelineBehavior<,> et les signatures des handlers sont identiques.
| Product | Versions 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. |
-
net10.0
NuGet packages (5)
Showing the top 5 NuGet packages that depend on CleanArch.DevKit.Mediator:
| Package | Downloads |
|---|---|
|
CleanArch.DevKit.Mediator.Validation
Source-generated fluent validation with a ValidationBehavior pipeline. Bridges to CleanArch.DevKit.Mediator. Part of the CleanArch.DevKit set. |
|
|
CleanArch.DevKit.Mediator.Results
Result<T> + Error model with railway-oriented extensions (Map / Bind / Match) and a ResultBehavior that auto-converts ValidationException into a ValidationError. Part of the CleanArch.DevKit set. |
|
|
CleanArch.DevKit.Mediator.Domain
Bridge between CleanArch.DevKit.Domain and CleanArch.DevKit.Mediator: IDomainEventNotification (combines IDomainEvent + INotification) and a typed PublishDomainEventsAsync extension on IMediator. Install this only if you use both Domain and Mediator together. Part of the CleanArch.DevKit set. |
|
|
CleanArch.DevKit.Mediator.Behaviors
Common pipeline behaviors (LoggingBehavior, PerformanceBehavior, UnhandledExceptionBehavior) for CleanArch.DevKit.Mediator. Part of the CleanArch.DevKit set. |
|
|
CleanArch.DevKit.Mediator.Testing
Mock-free testing helpers for CleanArch.DevKit.Mediator. FakeMediator with fluent setup and recording for IRequest, INotification and IStreamRequest. Part of the CleanArch.DevKit set. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.1 | 146 | 5/17/2026 |
| 1.1.0 | 131 | 5/17/2026 |
| 1.0.0 | 152 | 5/15/2026 |
| 0.1.0-preview.1 | 67 | 5/14/2026 |