2013-02-22 53 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