问题描述
在MVC,一个 ModelValidatorProvider
被实例化并调用以验证在每次请求的模型。这意味着在DI环境中,它可以依赖一个单一的请求中的对象范围,如工作或数据库环境的单位。在网页API,这似乎已显著改变。而不是每个请求被实例化时, ModelValidatorProvider
似乎是长寿命和应用程序启动中实例化。该的WebAPI然后缓存从 ModelValidatorProvider
每个类型的结果,这意味着 ModelValidator
不能采取任何依赖从DI。
In MVC, a ModelValidatorProvider
is instantiated and called to validate a model on each request. This means that in a DI environment, it can take dependencies on objects scoped within a single request, such as a Unit of Work or Database context. In Web API, this appears to have been significantly changed. Instead of being instantiated per-request, the ModelValidatorProvider
appears to be long-lived and instantiated within the application startup. The WebAPI then caches the results from the ModelValidatorProvider
per-type, meaning that the ModelValidator
cannot take any dependencies from DI.
我想实现我的 ModelValidator
来使用通过服务定位器工厂(请,没有自动的反模式的意见!)。这将让我的每个请求,这将能够从容器中取依赖性内构建一个内部验证的对象。但是,我无法依赖解析器的持有或容器内从该限制在当前请求 ModelValidator
这基本上是作用域为一个Singleton。我试图用 GlobalConfiguration.Configuration.DependencyResolver
,但这只是全球收益范围的服务(从根范围内,也的提到)
I am trying to implement my ModelValidator
to use a factory using a Service Locator (please, no automatic 'anti-pattern' comments!). This would allow me to construct an internal validator object within each request, which would be able to take dependencies from the container. However, I cannot get hold of a Dependency Resolver or container scoped to the current request from within this ModelValidator
which is essentially scoped as a Singleton. I've tried to use GlobalConfiguration.Configuration.DependencyResolver
, but this only returns globally-scoped services (from the root scope, also mentioned here)
我在Autofac工作,所以一个特定autofac的解决方案将是合适的(如MVC有 AutofacDependencyResolver.Current
,其内部使用 DependencyResolver .GetService
)。有一个在整合的WebAPI,presumably因为那里的全球 DependencyResolver
只返回全球范围的服务。
I'm working in Autofac, so an autofac-specific solution would be suitable (e.g. MVC has AutofacDependencyResolver.Current
, which internally uses DependencyResolver.GetService
). There is no equivalent available in the WebAPI integration, presumably because of the reason mentioned above where the global DependencyResolver
only returns globally-scoped services.
我试图做到这一点(以及我自己用的)的原因是为了落实FluentValidation,目前不存在的Web API集成。有过两次尝试,到目前为止,但这些都不处理依赖注入的问题,而是导致了在单一静态ModelValidator。
The reason I'm trying to do this (as well as for my own use) is to implement the Web API integration for FluentValidation, which currently does not exist. There have been two attempts so far, but neither of these handle the Dependency Injection issue and instead result in a single static ModelValidator.
事情到目前为止,我已经试过:
Things I've tried so far:
- 使用
GlobalConfiguration.Configuration.DependencyResolver
(从根范围内返回的对象) - 承担
Func键℃的依赖; IComponentContext>
(总是返回根上下文)
- Using
GlobalConfiguration.Configuration.DependencyResolver
(returns objects from the root scope) - Taking a dependency on
Func<IComponentContext>
(always returns the root context)
在这已经被删除的答案,有人建议从Web API的配置中删除 IModelValidatorProvider
服务。这不得不使用以来,接口和实现类都被定义为内部反射来实现,但它确实使验证工作得更好(因为ModelValidator为每个请求构建)。然而,打到这样做,由于使用反射检查型号和每一个拥有财产校验器显著的表现,所以我不想把这个选项。
In an answer which has since been removed, it was suggested to remove IModelValidatorProvider
service from the Web API config. This had to be done using reflection since the interface and the implementing classes are all defined as internal, but it did make the validators work better (because the ModelValidator was constructed per request). However, there is a significant performance hit to doing it this way due to the use of reflection to check for validators on the model and every property it has, so I don't want to take this option.
菲利普W公司的答案建议使用的Htt prequestMessage拿到依赖范围,但我没有发现任何东西,如的Htt prequestMessage.Current
这将提供访问该对象从长寿命的对象中 - 如果能够实现,我相信一切都会水到渠成。
Filip W's answer suggests using HttpRequestMessage to get the Dependency Scope, but I've not found anything such as HttpRequestMessage.Current
which would provide access to this object from within a long-lived object - if that could be achieved I believe everything would fall into place.
推荐答案
要获得当前的依赖范围,你必须使用(惊喜,惊喜:) GetDependencyScope()
的当前的Htt prequestMessage
(更多信息,你可以读了<一个href=\"http://msdn.microsoft.com/en-us/library/system.net.http.htt$p$pquestmessageextensions.getdependencyscope%28v=vs.108%29.aspx\"相对= MSDN上nofollow的>)代替 GlobalConfiguration
。
To get current dependency scope, you have to use (surprise, surprise :) GetDependencyScope()
of the current HttpRequestMessage
(more about which you can read up on MSDN) instead of GlobalConfiguration
.
我的博客上讲述的前一阵子 - 这应该是有帮助的。
I blogged about Web API per-request dependency scope a while ago - that should be helpful.
这篇关于每个请求DependencyResolver在网页API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!