2017-10-18 53 views
0

繼我在閱讀這些指南: https://www.devtrends.co.uk/blog/how-not-to-do-dependency-injection-the-static-or-singleton-container依賴注入 - 儘量避免使用服務定位器

我想盡量避免使用服務定位器。 但另一方面,我沒有註冊startup.cs文件中的所有類型。我不認爲這是正確的,所有這些內部類型在主startup.cs

引用我目前有一個工廠類具有建設者類的集合。 每個構建器類都負責創建特定的對象。 我不想提前創建所有這些構建器類,因爲我可能不需要使用它們,創建它們有點繁重。 我看到了一個如何在上面的鏈接中實現這個功能的例子。但是startup.cs類需要知道所有這些構建器。我不認爲這是合適的,我寧願讓工廠階級成爲唯一接觸他們的人。我試圖瞭解是否有某種func/action方法可以從startup.cs文件注入到我的工廠類中。這個功能/操作將負責創建/註冊建設者,然後我可以在班級工廠內激活這個功能/操作。我想要這個func/action來獲得接口/類/可能是構建器的名稱,但使用泛型不起作用。我搜索了很多,並沒有找到任何解決方案,所以我認爲這是不可能的。 似乎我有2個選項: 1.使用服務定位器。這種方式只有工廠類會知道建設者。但是如果將來,如果我想改變DI,我需要「觸摸」工廠類(我污染了工廠類)。希望所有的DI代碼只能位於startup.cs類中。 2.在startup.cs中註冊構建器,但現在startup.cs知道構建器。這有點夫婦的代碼,不是真正的單一角色的責任

這將是很好的注入工廠類從startup.cs func /動作將做註冊,但工廠類本身激活它。 這可能嗎?

+0

在單個類中註冊類型沒有任何問題。如果你想,你可以將它移動到一個配置文件。 – FCin

+0

那麼,我不喜歡配置文件,一般來說,儘量避免它們。在startup.cs中註冊所有類型 - 這看起來不太健康。如果我們想要更改構建器,我們需要「離開」工廠/構建器區域並跳轉到startup.cs並開始刪除/添加註冊。我認爲這是註冊一般組件的好地方,例如Logger/Configuration /等。但不是將我的所有類型加載到一個地方。 – TaLz

+0

您不要每小時更改一次舊的依賴關係,所以我不明白問題是如何去單個文件並更改一行代碼。 – FCin

回答

2

我想盡量避免使用服務定位器

大,因爲服務定位器is an anti-patttern

不要在startup.cs文件中註冊所有類型。

您應該在應用程序的一個「區域」中執行註冊:啓動路徑。這個區域通常被稱爲Composition Root(組成對象圖的地方)。

我不認爲這是正確的,所有這些內部類型在主startup.cs引用

不管你如何設計它,啓動組件的最不穩定的部分系統和它總是取決於所有應用程序中的其他程序集。直接或傳遞(通過另一個引用的程序集)。依賴注入的整個想法是儘量減少組件之間的耦合,並且這樣做的方法是通過將耦合移動到組合根來集中耦合。然而,通過內部類型,你是分散對象組成,並限制你的靈活性。例如,爲這些註冊類型應用裝飾器或攔截器並在全球範圍內控制它變得越來越困難。閱讀this question and its two top voted answers瞭解更多信息。

我不註冊的所有種類

其組成的根是太大的問題是不是有效的。人們可以很容易地將組合根分成多個更小的函數或類,它們都駐留在啓動程序集中。最重要的是,如果您閱讀this,您會明白,明確註冊所有類型(a.k.a.「顯式註冊」)通常毫無意義。在這種情況下,您最好使用沒有集裝箱的DI(a.k.a. Pure DI)。所有類型明確註冊的組合根並不是非常可維護的。 DI Container的強大之處在於其批量註冊設施。他們使用反射在幾行代碼中加載和註冊一組完整的類型。添加新類型不會導致您的Composition Root改變,從而爲您提供最高的可維護性。

我不想提前創建所有這些建設者類,因爲我可能不需要使用它們,創建它們是有點重實例

創作不應該是沉重的。您的injection constructors should be simple和撰寫對象圖should be reliable。這使得構建甚至是最大的對象圖非常快。工廠應減至an absolute minimum

TLDR;

  • 僅在組合根中註冊或撰寫對象圖。
  • 避免使用Service Locator反模式;整個應用程序可以(也應該)純粹使用構造函數注入來構建。
  • 使注入構造器變得簡單,並防止它們做任何事情而不是存儲其傳入的依賴關係。
  • 不要使用工廠來編寫服務,大多數情況下不需要它們。
+0

我不認爲這「服務定位器是一種反模式「。在源代碼的一些非常罕見的點內解決動態分辨率是非常有用的模式。濫用任何模式是很臭的 - 但這不是模式錯誤。 – Console

+0

@Console:服務定位器_is_是一種反模式,現在幾乎沒有關於這個問題的討論。但是您可能會對什麼是和什麼不是服務定位器感到困惑。下面是一篇[好文章](http://blog.ploeh.dk/2011/08/25/ServiceLocatorrolesvs.mechanics/),它解釋了並非每個使用「Resolve」方法的服務定位器都依賴於它的角色在系統中。 – Steven

+0

那麼如果你這樣說 - 它符合你所說的;)。我需要使用服務位置機制的架構代碼的另一個名稱,而不是 – Console