You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MediatR泛型Pipeline Behavior注册无效,如何正确注册?

问题原因与解决方案
  • 问题根源:你定义的LoggingPipeLineBehavior泛型约束过于具体,仅匹配IRequest<Result<TResult>>类型的请求,而MediatR在解析开放泛型Behavior时,无法正确将这种约束与具体请求(如CreateArtistCommand)关联,导致Behavior未被实例化执行。

  • 修复方案:

    1. 调整Behavior的泛型定义,使其适配所有请求类型,内部针对Result类型的返回做日志处理:
      首先确保你的Result<T>有一个非泛型基类(用于统一判断错误状态),示例基类:
      public abstract class ResultBase
      {
          public bool IsError { get; protected set; }
          public Error FirstError { get; protected set; }
      }
      
      public class Result<T> : ResultBase 
      {
          // 你的Result<T>原有实现
          public T Value { get; protected set; }
      }
      
      然后修改Behavior:
      public class LoggingPipeLineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
          where TRequest : IRequest<TResponse>
      {
          private readonly ILogger<LoggingPipeLineBehavior<TRequest, TResponse>> _logger;
      
          public LoggingPipeLineBehavior(ILogger<LoggingPipeLineBehavior<TRequest, TResponse>> logger)
          {
              _logger = logger;
          }
      
          public async Task<TResponse> Handle(
              TRequest request,
              RequestHandlerDelegate<TResponse> next,
              CancellationToken cancellationToken)
          {
              _logger.LogInformation("Starting request {@RequestName}, {@DateTimeUtc}",
                  typeof(TRequest).Name,
                  DateTime.UtcNow);
              
              var result = await next();
      
              if (result is ResultBase resultBase && resultBase.IsError)
              {
                  _logger.LogError("Request failure {@RequestName}, {@Error} {@DateTimeUtc}",
                      typeof(TRequest).Name,
                      resultBase.FirstError,
                      DateTime.UtcNow);
              }
              
              _logger.LogInformation("Completed request {@RequestName}, {@DateTimeUtc}",
                  typeof(TRequest).Name,
                  DateTime.UtcNow);
              
              return result;
          }
      }
      
    2. 保持原注册方式不变即可:
      var assembly = typeof(DependencyInjection).Assembly;
      
      services.AddMediatR(configuration =>
      {
          configuration.RegisterServicesFromAssembly(assembly);
          configuration.AddOpenBehavior(typeof(LoggingPipeLineBehavior<,>));
      });
      
  • 替代方案(无需非泛型Result基类):
    若不想修改Result类型结构,可通过反射判断返回类型是否为Result<T>并提取错误信息:

    public async Task<TResponse> Handle(
        TRequest request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Starting request {@RequestName}, {@DateTimeUtc}",
            typeof(TRequest).Name,
            DateTime.UtcNow);
        
        var result = await next();
    
        var resultType = result?.GetType();
        if (resultType != null && resultType.IsGenericType && resultType.GetGenericTypeDefinition() == typeof(Result<>))
        {
            var isErrorProp = resultType.GetProperty(nameof(Result<object>.IsError));
            var firstErrorProp = resultType.GetProperty(nameof(Result<object>.FirstError));
            
            if (isErrorProp != null && (bool)isErrorProp.GetValue(result) == true && firstErrorProp != null)
            {
                var error = firstErrorProp.GetValue(result);
                _logger.LogError("Request failure {@RequestName}, {@Error} {@DateTimeUtc}",
                    typeof(TRequest).Name,
                    error,
                    DateTime.UtcNow);
            }
        }
        
        _logger.LogInformation("Completed request {@RequestName}, {@DateTimeUtc}",
            typeof(TRequest).Name,
            DateTime.UtcNow);
        
        return result;
    }
    

内容的提问来源于stack exchange,提问作者qimbe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:45:57