Web API中的Per-Request DependencyResolver

时间:2013-02-22 14:25:53

标签: asp.net-web-api autofac fluentvalidation

在MVC中,实例化ModelValidatorProvider并调用它以在每个请求上验证模型。这意味着在DI环境中,它可以依赖于单个请求中作用域的对象,例如工作单元或数据库上下文。在Web API中,这似乎已经发生了重大变化。 ModelValidatorProvider似乎是在应用程序启动期间长期存在并实例化的,而不是按请求进行实例化。然后,WebAPI会缓存ModelValidatorProvider每类型的结果,这意味着ModelValidator无法从DI中获取任何依赖关系。

我正在尝试使用服务定位器来实现我的ModelValidator使用工厂(请不要自动“反模式”注释!)。这将允许我在每个请求中构造一个内部验证器对象,它可以从容器中获取依赖关系。但是,我无法获得依赖于当前请求的依赖关系解析器或容器作为当前请求,ModelValidator本质上是作为单例的范围。我尝试使用GlobalConfiguration.Configuration.DependencyResolver,但这只返回全局范围的服务(来自根范围,也是mentioned here

我在Autofac工作,因此特定于autofac的解决方案是合适的(例如MVC有AutofacDependencyResolver.Current,内部使用DependencyResolver.GetService)。 WebAPI集成中没有可用的等价物,可能是因为上面提到的全局DependencyResolver仅返回全局范围的服务的原因。

我尝试这样做(以及我自己使用)的原因是为FluentValidation实现Web API集成,目前不存在。到目前为止已经进行了两次尝试,但这些尝试都没有处理依赖注入问题,而是导致单个静态ModelValidator。

到目前为止我尝试过的事情:

  • 使用GlobalConfiguration.Configuration.DependencyResolver(返回根作用域中的对象)
  • 依赖Func<IComponentContext>(始终返回根上下文)

在已删除的答案中,建议从Web API配置中删除IModelValidatorProvider服务。这必须使用反射来完成,因为接口和实现类都被定义为内部,但它确实使验证器更好地工作(因为ModelValidator是按请求构造的)。但是,由于使用反射来检查模型上的验证器及其具有的每个属性,因此以这种方式执行它会有显着的性能损失,因此我不想采用此选项。

Filip W的回答建议使用HttpRequestMessage来获取依赖范围,但是我没有找到任何可以在长期存在的对象中提供对这个对象的访问的HttpRequestMessage.Current - 如果可以实现的话相信一切都会落实到位。

1 个答案:

答案 0 :(得分:4)

要获得当前的依赖范围,您必须使用当前GetDependencyScope()的(惊讶,惊讶:) HttpRequestMessage(更多关于您可以阅读的on MSDN)而不是{{ 1}}。

我刚才发表了关于Web API per-request dependency scope的博客 - 这应该会有所帮助。