Wolverine中间件直接返回结果的优雅实现方案咨询(从MediatR迁移场景)
Wolverine中间件直接返回结果的优雅实现方案咨询(从MediatR迁移场景)
兄弟,我太懂你从MediatR转Wolverine的适配痛点了——MediatR里Behavior直接返回结果的操作顺手得不行,换到Wolverine突然卡壳确实闹心😅。你说的这个“中间件直接返回结果、不用每个Handler都做判断”的需求完全合理,我之前踩过类似的坑,给你分享两个亲测有效的优雅方案:
方案一:泛型中间件(类型安全,针对特定消息/返回类型)
这个方案适合你有明确消息类型(比如InputDto)和返回类型(比如OutputDto)的场景,完全类型安全,代码也清爽:
1. 编写泛型授权中间件
public class AuthorizationMiddleware<TInput, TOutput> where TOutput : new() { public async Task<(HandlerContinuation, TOutput)> BeforeAsync(TInput input) { // 这里替换成你的实际授权逻辑 if (!IsUserAuthorized(input)) { // 授权失败时,直接返回终止信号+错误结果 return (HandlerContinuation.Stop, new TOutput { Valid = false }); } // 授权通过,继续执行Handler return (HandlerContinuation.Continue, default); } private bool IsUserAuthorized(TInput input) { // 示例:模拟授权失败 return false; } }
2. 精准绑定中间件到目标消息
注册时明确指定这个中间件只作用于InputDto类型的消息,避免全局冗余:
builder.UseWolverine(options => { options.Policies .ForMessagesOfType<InputDto>() .AddMiddleware<AuthorizationMiddleware<InputDto, OutputDto>>(); });
3. 控制器调用(无需修改原有代码)
你的原有Controller代码完全不用改,现在InvokeAsync会直接拿到中间件返回的OutputDto,不会再出现null的情况:
[HttpGet(Name = "GetWeatherForecast")] public async Task<OutputDto> Get() { var result = await _bus.InvokeAsync<OutputDto>(new InputDto { Id = 5 }); return result; // 现在能正确拿到Valid=false的结果 }
方案二:全局通用中间件(适配所有统一格式的返回结果)
如果你的系统里有很多类似的返回Dto(都带Valid属性),不想为每个消息写单独的泛型中间件,可以用这个更灵活的方案:
1. 编写全局授权中间件
利用Wolverine的IMessageContext来设置结果,反射处理通用返回类型:
public class GlobalAuthorizationMiddleware { public async Task<HandlerContinuation> BeforeAsync(IMessageContext context, object input) { // 这里替换成你的全局授权逻辑 if (!IsAuthorized(input)) { // 获取当前消息对应的Handler返回类型 var returnType = context.Message.Type.GetHandlerReturnType(); // 创建返回结果实例 var result = Activator.CreateInstance(returnType); // 设置Valid属性(假设所有返回Dto都有这个属性) returnType.GetProperty("Valid")?.SetValue(result, false); // 将结果绑定到Context,终止管道 context.SetResult(result); return HandlerContinuation.Stop; } return HandlerContinuation.Continue; } private bool IsAuthorized(object input) { // 通用授权判断逻辑 return false; } } // 扩展方法:获取Handler的返回类型 public static Type GetHandlerReturnType(this Type messageType) { // 示例简化逻辑:假设Handler命名为[MessageType]Handler,返回Task<T> var handlerType = Assembly.GetExecutingAssembly().GetTypes() .First(t => t.Name == $"{messageType.Name}Handler"); var handleMethod = handlerType.GetMethod("Handle"); var taskReturnType = handleMethod.ReturnType.GenericTypeArguments[0]; return taskReturnType; }
2. 全局注册中间件
builder.UseWolverine(options => { options.Policies.AddMiddleware<GlobalAuthorizationMiddleware>(); });
为什么你之前的代码会返回null?
你之前的中间件写法其实方向是对的,但问题出在中间件和消息/返回类型的绑定不明确——Wolverine无法自动推断非泛型中间件返回的OutputDto应该作为最终结果,用泛型中间件明确指定输入输出类型后,结果就能正确传递了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

