ASP.NET WebApi中基于Unity实现OWIN中间件的请求级依赖注入
解决ASP.NET WebApi(非DotNetCore)中Unity按请求实例化OWIN中间件的构造函数参数问题
嘿,我刚好踩过非Core ASP.NET WebApi + Unity + OWIN中间件的这个坑,给你理清楚问题根源和解决办法:
问题根源
你写的CustomMiddleware构造函数是完全符合OWIN中间件标准的——它需要接收OwinMiddleware next参数来串联管道,但Unity默认没办法直接处理OWIN管道传递的Func<Task>类型的next委托,因为你的构造函数期望的是OwinMiddleware实例,这就直接导致了编译错误。
正确的解决思路
我们需要把OWIN的Func<Task>委托包装成一个合法的OwinMiddleware子类实例,让Unity能把它作为参数注入到你的中间件构造函数里。具体步骤如下:
1. 编写OWIN委托包装类
这个类负责把OWIN管道的next委托转换成OwinMiddleware实例,适配你的构造函数要求:
public class OwinMiddlewareWrapper : OwinMiddleware { private readonly Func<Task> _nextFunc; public OwinMiddlewareWrapper(Func<Task> nextFunc) : base(null) { _nextFunc = nextFunc; } public override Task Invoke(IOwinContext context) { return _nextFunc(); } }
2. 编写Unity中间件注册扩展方法
用这个方法替代默认的Use<CustomMiddleware>(),让Unity按请求实例化中间件并注入正确的next参数:
public static class UnityOwinExtensions { public static IAppBuilder UseUnityMiddleware<T>(this IAppBuilder app, IUnityContainer container) where T : OwinMiddleware { return app.Use(async (context, next) => { // 用Unity解析中间件,同时传入包装后的next实例 var middleware = container.Resolve<T>( new ParameterOverride("next", new OwinMiddlewareWrapper(next)) ); await middleware.Invoke(context); }); } }
3. 在Startup中注册中间件
在Configuration方法里,用自定义扩展方法注册你的中间件,同时确保Unity容器已注册其他需要注入的依赖:
public void Configuration(IAppBuilder app) { // 初始化Unity容器并注册业务依赖 var container = new UnityContainer(); container.RegisterType<IMyService, MyService>(); // 示例:注册你的业务服务 // 用Unity按请求实例化中间件 app.UseUnityMiddleware<CustomMiddleware>(container); // 常规WebApi配置 var config = new HttpConfiguration(); config.MapHttpAttributeRoutes(); app.UseWebApi(config); }
4. 保持你的CustomMiddleware不变
你原来的中间件代码是正确的,甚至可以直接添加其他Unity需要注入的依赖:
public class CustomMiddleware : OwinMiddleware { // 可以添加其他Unity注入的依赖,比如业务服务 private readonly IMyService _myService; public CustomMiddleware(OwinMiddleware next, IMyService myService) : base(next) { _myService = myService; } public override async Task Invoke(IOwinContext context) { // 执行你的中间件逻辑,比如用_myService处理请求 await Next.Invoke(context); // 调用管道中的下一个中间件 } }
不推荐的替代方案(仅供参考)
如果你不想写包装类,也可以直接修改中间件构造函数接收Func<Task>,但这会破坏OWIN中间件的标准结构,后续扩展和维护会受限:
public class CustomMiddleware : OwinMiddleware { private readonly Func<Task> _next; public CustomMiddleware(Func<Task> next) : base(null) { _next = next; } public override async Task Invoke(IOwinContext context) { // 你的中间件逻辑 await _next(); } }
内容的提问来源于stack exchange,提问作者James Law
相关产品推荐
相关产品推荐

