8

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

我正在尝试ModelValidator使用服务定位器来实现我的使用工厂(请不要自动进行“反模式”评论!)。这将允许我在每个请求中构造一个内部验证器对象,该对象将能够从容器中获取依赖项。但是,我无法从 this 中获取范围为当前请求的 Dependency Resolver 或容器,ModelValidator它本质上是作为 Singleton 范围的。我试过使用GlobalConfiguration.Configuration.DependencyResolver,但这只会返回全局范围的服务(从根范围,也提到这里

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

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

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

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

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

Filip W 的回答建议使用 HttpRequestMessage 来获取 Dependency Scope,但我没有找到任何东西,例如HttpRequestMessage.Current可以从长期存在的对象中提供对该对象的访问 - 如果可以实现,我相信一切都会到位。

4

1 回答 1

4

要获得当前的依赖范围,您必须使用GetDependencyScope()当前的(surprise,surprise :) HttpRequestMessage(您可以在 MSDN 上阅读更多相关信息)而不是GlobalConfiguration.

不久前,我在博客上写了关于每个请求的 Web API 依赖范围- 这应该会有所帮助。

于 2013-02-22T14:59:38.473 回答