2013-05-31 67 views
8

我有一個靜態類,我需要注入一些實例。一個靜態類可以有一個靜態構造函數,但它必須是無參數的。那麼,我應該如何在其中注入某些東西?Ninject和靜態類 - 如何?

我不想創建一個單身人士。我希望有一個靜態類,它的一個方法對應該注入的實例進行操作。貝婁是我需要的一個例子。

public static class AuthenticationHelper 
{ 
    // Fields. 
    private static object _lock = new object(); 
    private static readonly UserBusiness _userBusiness; // <-- this field needs to be injected. 

    // Public properties. 
    public static User CurrentUser 
    { 
     get 
     { 
      if (IsAuthenticated) 
      { 
       User user = (User)Context.Session[SessionKeys.CURRENT_USER]; 

       if (user == null) 
       { 
        lock (_lock) 
        { 
         if (user == null) 
         { 
          user = _userBusiness.Find(CurrentUserId); 
          Context.Session[SessionKeys.CURRENT_USER] = user; 
         } 
        } 
       } 

       return user; 
      } 

      return null; 
     } 
    } 
    public static int CurrentUserId { get; /* implementation omitted for brevity */ } 
    public static bool IsAuthenticated { get; /* implementation omitted for brevity */ } 
} 

背景信息:這是一個MVC4應用程序,所以我使用ninject.mvc3插件。

PS:我見過一些關於Ninject和靜態方法的問題,但他們都沒有解決像這樣的問題。

在此先感謝。

回答

16

不要這樣做。不要使用需要它自己的依賴關係的靜態類。這使得測試更困難,而依賴於此的其他類型將無法將其包含在其構造函數中,這意味着它們隱藏了它們依賴於它的事實。

取而代之的只是做你永遠會做的事情:使AuthenticationHelper非靜態,實現一個接口,並通過其公共構造函數注入所有依賴。

但是,如果你堅持讓這個類保持靜態(這又是一個非常糟糕的主意),請在其上創建一個靜態的Initialize(UserBusiness userBusiness)方法,並在應用程序的啓動路徑中調用此方法。你不能讓你的DI容器調用這個靜態方法。他們不允許,因爲1.這是一個壞主意,並且2.這種靜態方法只需要調用一次,所以讓你的容器爲你自動連線這件事並沒有什麼幫助。

+0

我明白了。我沒有意識到這是一個很糟糕的做法,但通過你的解釋,我現在可以理解它,並會遵從你的建議。無論如何,如果沒有其他的選擇,知道如何解決這個問題是很好的。謝謝! –

+1

這是真的,有時你不能。例如,當向傳統應用程序引入依賴注入時,您將不得不小步移動。這些臨時步驟可能是這樣的解決方案。這是醜陋的,它是技術深度,但暫時的(至少應該是)。但是如果您的應用程序已經使用DI構建,那麼確實沒有理由這樣做。 – Steven

1

作爲一個方面說明,鎖是完全無用的,因爲您正在鎖定對「if(user == null)」行之間不會改變的局部變量「user」的訪問。

你的目的是要鎖定訪問Context.Session [CURRENT_USER]元素,所以..

  User user = (User)Context.Session[SessionKeys.CURRENT_USER]; 

      if (user == null) 
      { 
       lock (_lock) 
       { 
        user = (User)Context.Session[SessionKeys.CURRENT_USER]; 
        if (user == null) 
        { 
         user = _userBusiness.Find(CurrentUserId); 
         Context.Session[SessionKeys.CURRENT_USER] = user; 
        } 
       } 
      }