【发布时间】:2013-02-25 05:15:19
【问题描述】:
在 MVC 中,ModelValidatorProvider 被实例化并调用以验证每个请求的模型。这意味着在 DI 环境中,它可以依赖于单个请求范围内的对象,例如工作单元或数据库上下文。在 Web API 中,这似乎已经发生了重大变化。 ModelValidatorProvider 似乎是长期存在的,并在应用程序启动时被实例化,而不是按请求实例化。然后,WebAPI 缓存每个类型的 ModelValidatorProvider 的结果,这意味着 ModelValidator 不能从 DI 获取任何依赖项。
我正在尝试实现我的ModelValidator 以使用使用服务定位器的工厂(请不要使用自动“反模式”cmets!)。这将允许我在每个请求中构造一个内部验证器对象,它能够从容器中获取依赖项。但是,我无法从这个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 来获取 Dependency Scope,但我没有找到诸如 HttpRequestMessage.Current 之类的任何东西,它可以从长期存在的对象中提供对该对象的访问 - 如果可以实现的话,我相信一切会到位。
【问题讨论】:
标签: asp.net-web-api autofac fluentvalidation