2013-02-22 51 views
8

在MVC中,实例化一个ModelValidatorProvider并调用它以验证每个请求上的模型。这意味着在DI环境中,它可以依赖于单个请求范围内的对象,例如工作单元或数据库上下文。在Web API中,这似乎发生了重大变化。代替每个请求实例化,ModelValidatorProvider似乎是在应用程序启动时长期存在和实例化的。 WebAPI然后缓存来自每个类型的ModelValidatorProvider的结果,这意味着ModelValidator不能从DI获得任何依赖关系。Web API中的每个请求依赖关系解析器

我想实现我的ModelValidator使用服务定位器的工厂(请不要自动'反模式'的意见!)。这将允许我在每个请求中构造一个内部验证器对象,这将能够从容器中获取依赖关系。但是,我无法得到这个ModelValidator中的当前请求范围内的依赖项解析器或容器,它基本上被定义为一个Singleton。我试着用GlobalConfiguration.Configuration.DependencyResolver,但是这只是回报全球范围的服务(从根范围内,也mentioned here

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

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

事情我试过到目前为止:

  • 使用GlobalConfiguration.Configuration.DependencyResolver(返回从根范围对象)
  • 承担Func<IComponentContext>(总是返回根上下文)

的依赖在一个已被删除的答案,建议从Web API配置中删除IModelValidatorProvider服务。这必须使用反射来完成,因为接口和实现类都被定义为内部的,但它确实使验证器更好地工作(因为ModelValidator是根据请求构造的)。但是,由于使用了反射来检查模型上的验证器以及它的每个属性,所以这样做会产生显着的性能影响,所以我不想采用此选项。

菲利普W公司的答案建议使用HttpRequestMessage得到相关范围,但我没有发现任何诸如HttpRequestMessage.Current这将提供从长寿命对象中访问该对象 - 如果这可以实现,我相信一切都会到位。

回答

3

为了获得当前的依赖范围,你必须使用(惊奇,惊奇:)当前HttpRequestMessageGetDependencyScope()(更多相关信息,您可以阅读起来on MSDN),而不是GlobalConfiguration

前段时间我在博客上写了Web API per-request dependency scope - 这应该会有帮助。

+6

听起来像它可能更接近解决方案,但我如何获得HttpRequestMessage?这是来自长时间运行的课程。谷歌搜索表明这也是不可能的。 – Richard 2013-02-22 16:40:26