MediatR 12.2.0日志Behavior注册失败,求排查方案
MediatR日志Pipeline Behavior注册后未生效问题排查
问题描述
我尝试使用MediatR实现简单的日志Pipeline Behavior,在Program.cs中尝试了以下三种注册方式,但均未生效:
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));cfg.AddOpenBehavior(typeof(LoggingBehavior<,>));builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
相关代码如下:
日志Behavior实现代码
using MediatR; using Microsoft.Extensions.Logging; namespace CAS.TimeSheet.Application.Behaviors; public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse> { private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger; public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger) { _logger = logger; } public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken) { _logger.LogInformation($"Handling {typeof(TRequest).Name}"); var response = await next(); _logger.LogInformation($"Handled {typeof(TResponse).Name}"); return response; } }
MediatR注册代码
builder.Services.AddMediatR(cfg => { cfg.RegisterServicesFromAssemblyContaining<HolidayService>(); // cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); // cfg.AddOpenBehavior(typeof(LoggingBehavior<,>)); }); // builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
问题排查与解决
1. 程序集扫描范围未覆盖Behavior类
当前使用RegisterServicesFromAssemblyContaining<HolidayService>()注册MediatR服务,但LoggingBehavior位于CAS.TimeSheet.Application.Behaviors命名空间下,需要确认HolidayService所在程序集是否包含该Behavior类。如果两者不在同一个程序集(比如HolidayService在基础设施层,Behavior在应用层),MediatR的自动扫描不会发现这个Behavior。
解决办法:
- 改为从Behavior所在程序集注册:
cfg.RegisterServicesFromAssemblyContaining<LoggingBehavior<,>>(); - 或者同时注册两个程序集:
cfg.RegisterServicesFromAssemblyContaining<HolidayService>(); cfg.RegisterServicesFromAssemblyContaining<LoggingBehavior<,>>();
2. 注册方式与顺序问题
推荐在AddMediatR的配置块内使用AddOpenBehavior注册泛型开放类型的Behavior,这是MediatR官方推荐的方式。同时要确保注册代码在程序集扫描之后(或同时完成扫描)。
正确注册示例:
builder.Services.AddMediatR(cfg => { cfg.RegisterServicesFromAssemblyContaining<HolidayService>(); cfg.RegisterServicesFromAssemblyContaining<LoggingBehavior<,>>(); cfg.AddOpenBehavior(typeof(LoggingBehavior<,>)); });
3. 日志级别未配置为Information
如果应用默认日志级别高于Information(比如Warning),LogInformation的内容不会被输出,会让你误以为Behavior没执行。
检查并修改appsettings.json:
确保日志配置包含Information级别:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } } }
4. 请求未通过IMediator发送
只有通过IMediator.Send()方法发送请求,Pipeline Behavior才会被触发。如果直接实例化Handler并调用其Handle方法,Behavior不会生效。
正确调用方式:
// 正确:通过IMediator发送请求 var response = await _mediator.Send(new YourRequest()); // 错误:直接调用Handler,跳过Pipeline var handler = new YourRequestHandler(); var response = await handler.Handle(new YourRequest(), cancellationToken);
内容的提问来源于stack exchange,提问作者Hamed Naghdi
相关产品推荐
相关产品推荐

