在 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
可以从长期存在的对象中提供对该对象的访问 - 如果可以实现,我相信一切都会到位。