Offside.MediatR conecta valores Result com falha a notificações MediatR sem adicionar MediatR ao pacote Core do Offside. Uma notificação sempre carrega um Error; ela não é um domain event que descreve mudança de estado.
dotnet add package Offside
dotnet add package Offside.MediatR
Configure o MediatR primeiro e depois a integração:
using Offside.MediatR;
builder.Services.AddMediatR(configuration =>
configuration.RegisterServicesFromAssemblyContaining<Program>());
builder.Services.AddOffsideMediatR();
AddOffsideMediatR é idempotente. Ele registra um coletor scoped e seu notification handler, mas não chama AddMediatR, não registra IPublisher e não configura licença do MediatR.
Não é necessário escanear o assembly Offside.MediatR. Se ele for escaneado, o coletor protege uma mesma instância de notificação contra registro duplicado do handler.
Injete IPublisher e publique na borda da aplicação:
public async Task<Result> Cancel(string id, CancellationToken cancellationToken)
{
var result = _orders.Cancel(id);
return await result.PublishDomainNotificationsAsync(_publisher, cancellationToken);
}
O overload genérico devolve o mesmo Result<T>:
Result<Order> result = _orders.Get(id);
return await result.PublishDomainNotificationsAsync(_publisher, cancellationToken);
Sucesso não publica nada. Falha publica uma DomainNotification por erro, sequencialmente e na ordem do Result. Com E erros e H handlers, o limite de trabalho é E × H execuções de handler.
Injete IDomainNotificationCollector no mesmo scope de injeção de dependência:
if (collector.HasNotifications)
return collector.ToResult();
return collector.ToResult(order);
Errors devolve um snapshot independente. ToResult() devolve sucesso quando vazio e falha com os erros coletados nos demais casos. ToResult<T>(value) devolve o valor informado apenas quando o coletor está vazio.
Leituras nunca removem notificações; não existe Clear. Crie um scope por operação lógica:
await using var scope = scopeFactory.CreateAsyncScope();
var worker = scope.ServiceProvider.GetRequiredService<OrderWorker>();
await worker.Process(message, stoppingToken);
O ASP.NET Core já cria um scope por request. Workers devem criar um novo scope por mensagem ou job; reutilizar um scope longo também mantém erros antigos.
Todo handler recebe o Error completo, incluindo Arguments e dados de diagnóstico de Unexpected. A sanitização HTTP não é executada nesse caminho. Nunca coloque segredos em um erro.
O pacote suporta MediatR 12.0.1 até 14.x e é testado com 12.0.1, 13.1.0 e 14.2.0. O intervalo da dependência NuGet é [12.0.1,15.0.0).
O MediatR 13 introduziu uma chave de licença e mudou seu modelo de licenciamento upstream. Hosts com 13 ou 14 devem configurar logging e avaliar a licença aplicável. Configure a chave no próprio MediatR; o Offside não aceita uma chave nem suprime warnings de licença. Veja a release do MediatR 13 e a página oficial de licenciamento.
Clear: o scope controla o ciclo de vida do coletor.