MediatR泛型Pipeline Behavior注册无效,如何正确注册?
问题原因与解决方案
问题根源:你定义的
LoggingPipeLineBehavior泛型约束过于具体,仅匹配IRequest<Result<TResult>>类型的请求,而MediatR在解析开放泛型Behavior时,无法正确将这种约束与具体请求(如CreateArtistCommand)关联,导致Behavior未被实例化执行。修复方案:
- 调整Behavior的泛型定义,使其适配所有请求类型,内部针对Result类型的返回做日志处理:
首先确保你的Result<T>有一个非泛型基类(用于统一判断错误状态),示例基类:
然后修改Behavior: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; } }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; } } - 保持原注册方式不变即可:
var assembly = typeof(DependencyInjection).Assembly; services.AddMediatR(configuration => { configuration.RegisterServicesFromAssembly(assembly); configuration.AddOpenBehavior(typeof(LoggingPipeLineBehavior<,>)); });
- 调整Behavior的泛型定义,使其适配所有请求类型,内部针对Result类型的返回做日志处理:
替代方案(无需非泛型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
相关产品推荐
相关产品推荐

