4

假設我有一個BaseForm這取決於​​或IResourceManager或類似的東西。目前它使用我知道是反模式的服務定位器來解決所需服務的正確實現。混淆了使用IOC容器,服務定位器和工廠

  • 正在使用構造函數注入正確的方式來解決這種依賴?
  • 我是否必須在容器中註冊我的BaseForm(及其派生類型)以創建具有已解決依賴項的實例?這不是使一切複雜化?
  • 使用圍繞服務定位器的靜態工廠是不好的?
  • 單元測試放在一邊,我真的會因爲使用服務定位器反模式而受到懲罰嗎?

很抱歉,一次詢問很多問題。我讀過以下的SO問題和其他許多人,但閱讀它們只是添加到我的困惑:

回答

8

如果可能的話,你應該總是去依賴注射,因爲它有一些清晰的實力。然而,使用UI技術,並不總是可以使用依賴注入,因爲一些UI技術(例如在.NET空間,Win Forms和Web Forms中)只允許你的UI類(表單,頁面,控件等)擁有一個默認的構造函數。在這種情況下,您將不得不退回到其他服務定位器。

在這種情況下,我可以給你以下建議:

  • 只有回落到服務定位器對於無法通過你的容器使用依賴注入來創建UI類,以及東西,你不是活得無論如何t單元測試。
  • 儘量在這些UI類中實現儘可能少的邏輯(因爲Humble objects只有視圖相關的東西)。這可以讓你儘可能地進行單元測試。
  • 圍繞靜態方法包裝容器以隱藏容器與應用程序的其餘部分。當依賴關係無法解析時,請確保對此靜態方法的調用失敗。
  • 解決該類型的(默認)構造函數中的所有依賴項。這允許應用程序在創建該類型時無法解析其某個依賴項時發生故障,而不是在稍後單擊某個按鈕時解決。
  • 在應用程序啓動期間(或使用單元測試)檢查是否可以創建所有這些UI類型。這使您不必通過整個應用程序(通過打開所有窗體)來查看DI配置中是否有錯誤。
  • 當容器無法構建類型時,沒有理由在容器中註冊它們。如果它們可以由容器創建(例如使用ASP.NET MVC控制器類),則明確註冊它們會很有用,因爲某些容器允許您預先驗證配置,這將檢測這些類型中的配置錯誤遠。

除了單元測試,也有反對使用了服務定位器,這是由馬克·西曼在他著名的博客文章Service Locator is an Anti-Pattern給出的另外兩個重要的參數:

  • 服務定位器「隱藏一個類依賴關係,導致運行時錯誤而不是編譯時錯誤」
  • 服務定位器‘使代碼更難以維護’
+0

什麼非UI類?我不想在容器內註冊所有的依賴類(不是組件或服務)。 – reticent

+0

對於其他一切,請使用DI並確保容器可以解決它們。大多數容器允許您進行批量註冊,這意味着您可以在一個(或幾個)語句中註冊一整套(相關)組件。這可以讓您的作文根部小巧且可維護。 – Steven