2010-05-31 52 views
2

NInject和我有在多線程環境下面的類問題線程安全

public class Foo 
{ 
    [Inject] 
    public IBar InjectedBar { get; set; } 
    public bool NonInjectedProp { get; set; } 

    public void DoSomething() 
    { 
     /* The following line is causing a null-reference exception */ 
     InjectedBar.DoSomething(); 
    } 

    public Foo(bool nonInjectedProp) 
    { 
     /* This line should inject the InjectedBar property */ 
     KernelContainer.Inject(this); 
     NonInjectedProp = nonInjectedProp; 
    } 
} 

這是一個遺留類,這是爲什麼我使用的財產,而不是構造函數注入。

有時,當調用DoSomething()時,InjectedBar屬性爲null。在單線程應用程序中,一切運行良好。

這怎麼可能發生,我該如何防止它呢?

雖然我已經從NInject.Web項目複製了KernelContainer,但我使用NInject 2.0時沒有任何擴展名。

我注意到我的web服務中發生了類似的問題。這個問題非常時斷時續,難以複製。

+0

你的環境是什麼?即你在WCF中託管?什麼版本的ninject?你在用什麼擴展項目? – 2010-06-02 13:39:34

+0

你可以在單元測試中複製嗎? – 2010-06-02 14:01:46

+0

NInject 2.0,不支持擴展。 KernelContainer與NInject.Web中的相同。 – cbp 2010-06-03 00:49:59

回答

2

首先,讓我說這在很多層面上都是錯誤的; KernelContainer是保持,特別是的基礎結構類,以解決ASP.NET WebForms頁生命週期中的某些限制。它從來不打算在應用程序代碼中使用。使用Ninject內核(或任何DI容器)作爲服務定位器is an anti-pattern。這就是說,Ninject本身絕對是線程安全的,因爲它一直用於在ASP.NET中處理並行請求。無論這個NullReferenceException來自哪裏,與Ninject都沒什麼關係。

我能想到的兩種可能性:

  1. 您必須初始化KernelContainer.Kernel顯山露水,代碼可能有一個競爭條件。如果在內核完全初始化之前嘗試使用KernelContainer(如果按照指導使用IKernel.Bind方法而不是加載模塊,則可能會出現這種情況),則會出現類似的錯誤。或者:

  2. 這是你的IBar實現本身有問題,而NullReferenceException在某處發生的DoSomething方法內。當你得到異常時,你實際上並沒有指定InjectedBarnull,所以這在這裏是合理的可能性。

只是爲了縮小可能性領域,我會先消除KernelContainer。如果您絕對必須使用Ninject作爲服務定位器,原因是遺留下來的架構設計不佳,那麼至少允許它創建依賴關係而不是依賴於Inject(this)。也就是說,無論哪一類或哪幾類需要創建你的Foo,有類呼叫kernel.Get<Foo>(),並設置你的內核到Bind<Foo>().ToSelf()