Comportamentos de pipeline
Adicione lógica transversal com comportamentos.
Comportamentos de pipeline é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.
Preocupações transversais
Registro, validação, medição de tempo e transações se aplicam a muitos handlers. Copiar esse código para cada handler é repetitivo e propenso a erros.
Os comportamentos do canal de processamento do MediatR permitem envolver cada solicitação com lógica compartilhada.
// One behavior runs around all handlersComportamento do canal de processamento
Um comportamento implementa IPipelineBehavior<TRequest, TResponse>. Seu método Handle recebe a solicitação e um delegado next que invoca o restante do canal de processamento.
public class LoggingBehavior<TRequest, TResponse>
: IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken ct)
{
// before
var response = await next();
// after
return response;
}
}O delegado seguinte
next() chama o comportamento seguinte ou o handler real se este for o último. O código antes da chamada é executado durante a entrada; o código depois é executado durante a saída.
// [Behavior A in] -> [Behavior B in] -> [Handler]
// <- [Behavior B out] <- [A out]Um comportamento de registro
Um comportamento concreto de registro anota o nome da solicitação durante a entrada e o tempo decorrido durante a saída.
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken ct)
{
var name = typeof(TRequest).Name;
_logger.LogInformation("Handling {Name}", name);
var sw = Stopwatch.StartNew();
var response = await next();
_logger.LogInformation("{Name} took {Ms}ms", name, sw.ElapsedMilliseconds);
return response;
}Registrando um comportamento
Registre o comportamento genérico aberto em DI. O MediatR o aplica a todas as solicitações.
builder.Services.AddTransient(
typeof(IPipelineBehavior<,>),
typeof(LoggingBehavior<,>));Um comportamento de validação
Um uso comum é validar solicitações com FluentValidation. O comportamento executa todos os validadores antes que o handler seja executado e lança uma exceção se algum deles falhar.
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken ct)
{
var context = new ValidationContext<TRequest>(request);
var failures = _validators
.Select(v => v.Validate(context))
.SelectMany(r => r.Errors)
.Where(f => f is not null)
.ToList();
if (failures.Count != 0)
throw new ValidationException(failures);
return await next();
}Interrupção antecipada
Um comportamento pode ignorar completamente o handler retornando sem chamar next() — algo útil para armazenar resultados de consultas em cache ou rejeitar solicitações inválidas.
if (_cache.TryGet(key, out TResponse cached))
return cached; // handler never runs
var response = await next();
_cache.Set(key, response);
return response;Ordenando comportamentos
Os comportamentos são executados na ordem em que foram registrados. Coloque o registro na camada mais externa, depois a validação e, em seguida, as transações, para que cada um envolva corretamente o próximo.
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(TransactionBehavior<,>));Um comportamento de transação
Envolva os handlers de comandos em uma transação de banco de dados para que toda a operação seja confirmada ou revertida atomicamente.
await using var tx = await _db.Database.BeginTransactionAsync(ct);
try
{
var response = await next();
await tx.CommitAsync(ct);
return response;
}
catch
{
await tx.RollbackAsync(ct);
throw;
}Direcionando solicitações específicas
Use uma interface marcadora e uma restrição genérica para que um comportamento se aplique apenas às solicitações que optarem por ele — por exemplo, somente os comandos recebem transações.
public interface ITransactional { }
public record CreateOrderCommand(...) : IRequest<int>, ITransactional;
// where TRequest : ITransactionalPor que os comportamentos superam o intermediário HTTP
Ao contrário do intermediário HTTP, os comportamentos são executados por mensagem, recebem a solicitação e a resposta tipadas e funcionam mesmo quando uma solicitação é encaminhada fora do HTTP, por exemplo, a partir de uma tarefa em segundo plano.
// Strongly typed, transport-independent cross-cutting logicVerificação rápida
Confirme como os comportamentos funcionam.
Recapitulação
Você aprendeu sobre os comportamentos do canal de processamento:
IPipelineBehavior<TRequest, TResponse>envolve cada solicitação com lógica compartilhada.- O delegado
nextavança pelo canal de processamento; ignorá-lo interrompe o handler. - Usos comuns: registro, validação, transações e armazenamento em cache.
- Os comportamentos são executados na ordem de registro e são fortemente tipados.
Próximo tópico: notificações e eventos.
Aprenda C# com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 93
- Aulas
- 346
Perguntas Frequentes
A aula “Comportamentos de pipeline” é grátis?
Sim — o texto completo de “Comportamentos de pipeline” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.
O que vou aprender em “Comportamentos de pipeline”?
Adicione lógica transversal com comportamentos. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar C# Academy?
Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Comportamentos de pipeline”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de C# Academy?
Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Conceitos de CQRS
- Comandos e manipuladores com MediatR
- Comportamentos de pipeline
- Notificações e eventos