MediatR中自定义泛型PipelineBehavior(Behavior_2)未触发的问题及实现需求咨询
我来帮你分析和解决这个问题,你核心想让类似Behavior_2的PipelineBehavior正常触发,并且能在验证不通过时提前返回失败的QueryResult对吧?咱们先拆解问题原因,再给出可行的解决方案。
为什么Behavior_2没被触发?
问题出在MediatR对开放泛型PipelineBehavior的匹配规则上。你定义的Behavior_2<TQuery, TResult>实现的是IPipelineBehavior<TQuery, QueryResult<TResult>>,但MediatR在匹配行为时,要求行为的第二个泛型参数必须直接对应请求的返回类型(也就是IRequest<TResponse>里的TResponse)。
你的PingQuery实现了IQuery<Pong>,而IQuery<TResult>继承自IRequest<QueryResult<TResult>>,所以PingQuery对应的返回类型是QueryResult<Pong>。但Behavior_2的第二个泛型参数是QueryResult<TResult>,这相当于让MediatR去匹配一个“泛型嵌套泛型”的返回类型,它没法自动推断出TResult对应的实际类型是Pong,因此就跳过了这个行为。
解决方案:调整Behavior_2的泛型约束
我们需要修改Behavior_2的泛型定义,让它能精准匹配返回类型为QueryResult<TResult>的请求。修改后的代码如下:
public class Behavior_2<TRequest, TResult> : IPipelineBehavior<TRequest, QueryResult<TResult>> where TRequest : IRequest<QueryResult<TResult>> { public async Task<QueryResult<TResult>> Handle(TRequest request, RequestHandlerDelegate<QueryResult<TResult>> next, CancellationToken cancellationToken) { Console.WriteLine($"'{GetType()}' is processing '{request.GetType()}'"); if (!DoSomeValidation()) { // 验证不通过时直接返回失败的QueryResult,跳过后续handler执行 return new QueryResult<TResult> { Succeeded = false, Error = "Validation failed" }; } var result = await next(cancellationToken); return result; } private static bool DoSomeValidation() => false; }
关键修改点说明
- 泛型参数调整为
TRequest和TResult,并给TRequest加上IRequest<QueryResult<TResult>>的约束,完美匹配你定义的IQuery<TResult>(因为IQuery<TResult>本身就继承自IRequest<QueryResult<TResult>>) - 现在MediatR可以清晰识别到所有返回
QueryResult<TResult>的请求,自然会触发这个行为
额外优化:只针对IQuery类型的请求生效
如果你希望这个行为只处理实现了IQuery<TResult>的请求,而不是所有返回QueryResult<TResult>的IRequest,可以把约束改成更精准的:
where TRequest : IQuery<TResult>
注册代码无需修改
你原来的服务注册代码保持不变即可:
services.AddMediatR(configuration => { configuration.RegisterServicesFromAssembly(typeof(Program).Assembly); configuration.AddOpenBehavior(typeof(Behavior_1<,>)); configuration.AddOpenBehavior(typeof(Behavior_2<,>)); });
现在重新测试发送PingQuery,Behavior_2就会正常触发,并且在验证失败时提前返回错误结果,不会执行后续的PingQueryHandler。
内容来源于stack exchange

