2015-09-17 74 views
2

在靜態構造函數中初始化簡單注入器容器是否合法?在靜態構造函數中初始化容器

例子:

using SimpleInjector; 

public static Bootstrapper 
{ 
    private readonly static Container container; 

    static Bootstrapper() 
    { 
     Bootstrapper.container = new Container(); 
    } 
} 
+0

將容器暴露爲公共靜態字段讓我感到害怕。你使用容器作爲服務定位器嗎? –

+1

爲了保持技術性和清晰度,我會在我的問題中將其設爲「私人」。 – QuantumHive

回答

3

正如@NedStoyanov所說,一個靜態構造函數保證了唯一性,所以這可能是有益的。然而,靜態構造函數的缺點是它們通常更難以調試,並且從cctor主體拋出的任何異常都被包裝在InitializationException中,這使得很難看到實際問題。

我也不想重複@ WSriramSakthivel的警告:儘管在你的根組成的Container聲明爲public readonly static場,防止訪問本場組成的根,只要有可能。從組合根外使用它意味着應用Service Locator anti-pattern

請注意,使用cctor來初始化您的容器也可能有缺點。在集成測試中驗證容器並運行一些使用容器來構建對象圖的集成測試時,通常希望讓每個測試都有自己的容器實例,並使用自己的稍微不同的配置。這是你在使用cctor時無法使用的東西。

所以長話短說,雖然使用cctor可能是罰款,並給出了一些不錯的保障,我認爲在大多數情況下,它只會在路上。

1

應該OK,該static構造是保證只有一次前首次使用該類型是線程安全的調用。

從speicification

靜態構造函數不能被繼承,並且不能直接調用。 封閉類類型的靜態構造函數在給定應用程序域中最多執行一次。

靜態構造函數的執行是由應用程序域內發生以下第一個事件觸發的:
•創建類類型的實例。
•引用類類型的任何靜態成員。

2

以我的經驗,你應該儘量避免在大多數情況下的靜態實例。想象一下,容器的生命週期與應用程序的生命週期相匹配。換句話說,如果您將容器設爲靜態,它將保持活動狀態,直到應用程序關閉。

要獲得更好的實踐,請找到應用程序的入口點。我們假設它是static void Main()。在這種情況下,請在此處創建容器的實例,並使用此容器創建啓動對象(Windows,Forms等)。

如果你正確地設計你的DI,你不應該在以後的應用程序中需要容器容器。只要確保服務(在容器註冊)通過構造函數注入需要的對象。

此外,請檢查出Service Locator violates SOLID by Mark Seemann。馬克在DI上有很多帖子,並解釋了爲什麼這是一個糟糕的做法。

+0

「如果你正確設計你的DI,你不應該在應用程序中稍後需要容器對象。」我同意,但我的問題不是關於設計原則。我只是好奇,如果它在技術上是合法的(因爲也許容器的初始化需要在程序集中的所有靜態構造函數被調用後發生?我不知道技術細節,因此我的問題:) – QuantumHive

+0

容器不知道有關特定於應用程序的類及其靜態構造函數的任何信息。所以它是*可能*在靜態構造函數中初始化它。不過,這並不一定是最好的。 @decyclone在解釋原因方面做得很好。 –

相關問題