Conformité · CQRS · Mapperly
Sortir de MediatR et AutoMapper, en production
MediatR et AutoMapper passent en dual-license. 100+ handlers à migrer sans interrompre les livraisons.
- 100+
- handlers migrés
- 9
- profils de mapping
- 0
- interruption de livraison
Le problème
MediatR et AutoMapper annoncent un passage en dual-license. Plus de 100 handlers CQRS et 9 profils de mapping en dépendent, sur une plateforme en production, sans fenêtre de maintenance disponible pour tout réécrire d'un coup.
L'approche
La migration a été menée handler par handler derrière l'abstraction existante : un dispatcher OSS custom a remplacé MediatR sans changer la signature des handlers, et Mapperly a remplacé AutoMapper — ses mappers sont générés à la compilation plutôt que résolus par réflexion à l'exécution.
// MediatR moved to a dual licence in 2025. Rather than accept the risk or
// pay for 100+ handlers we already owned, the dispatch surface was replaced
// with the smallest thing that satisfied our actual usage: send, and nothing
// else. No pipelines, no notifications, no reflection at runtime.
public interface IRequestHandler<in TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
Task<TResponse> HandleAsync(TRequest request, CancellationToken ct);
}
public sealed class Dispatcher(IServiceProvider provider) : IDispatcher
{
public Task<TResponse> SendAsync<TResponse>(
IRequest<TResponse> request, CancellationToken ct = default)
{
// Handlers are resolved by closed generic type, so a missing
// registration fails at startup rather than at first request.
var handlerType = typeof(IRequestHandler<,>)
.MakeGenericType(request.GetType(), typeof(TResponse));
dynamic handler = provider.GetRequiredService(handlerType);
return handler.HandleAsync((dynamic)request, ct);
}
}Le résultat
100+ handlers et 9 profils de mapping migrés sans interrompre les livraisons ni introduire de régression fonctionnelle, avec en prime un mapping plus rapide : la génération à la compilation élimine le coût de réflexion d'AutoMapper.