2009-08-18 58 views

回答

24

您無法注入靜態記錄器。您必須將其更改爲實例記錄器(如果可以的話),或者將其包裝到實例記錄器中(這將調用靜態)。此外,向靜態類注入任何東西都相當困難(因爲您不以任何方式控制靜態構造函數) - 這就是爲什麼我傾向於將所有想要注入的對象作爲參數傳遞的原因。

21

這不一定如此。只要你的靜態記錄公開了一種方法:在類似的ASP運行它(比如之前的類

  • 注入你想注入,或
  • 注射的DI容器在適當的方法調用.net global.asax Application_Start方法),那麼你應該沒問題。

下面是一個例子。看看下面的類DI:

public class Logger : ILogger 
    { 
     public void Log(string stringToLog) 
     { 
      Console.WriteLine(stringToLog); 
     } 
    } 

    public interface ILogger 
    { 
     void Log(string stringToLog); 
    } 

下面是我們的靜態類,它需要一個記錄:

public static class SomeStaticClass 
    { 
     private static IKernel _diContainer; 
     private static ILogger _logger; 

     public static void Init(IKernel dIcontainer) 
     { 
      _diContainer = dIcontainer; 
      _logger = _diContainer.Get<ILogger>(); 
     } 


     public static void Log(string stringToLog) 
     { 
      _logger.Log(stringToLog); 
     } 


    } 

現在,在全球啓動了您的應用程序(在這種情況下,我的Global.asax .cs),你可以實例化你的DI容器,然後把它交給你的靜態類。

public class Global : Ninject.Web.NinjectHttpApplication 
    { 

     protected override IKernel CreateKernel() 
     { 
      return Container; 
     } 


     static IKernel Container 
     { 
      get 
      { 
       var standardKernel = new StandardKernel(); 
       standardKernel.Bind<ILogger>().To<Logger>(); 
       return standardKernel; 
      } 

     } 

     void Application_Start(object sender, EventArgs e) 
     { 
      SomeStaticClass.Init(Container); 
      SomeStaticClass.Log("Dependency Injection with Statics is totally possible"); 

     } 

而且急!你現在已經開始在你的靜態類中使用DI了。

希望能幫助別人。我正在重新開發一個使用很多靜態類的應用程序,我們現在已經成功地使用了它。

+5

在我看來更像是依賴解析比依賴注入。靜態類現在已經瞭解了依賴框架。但要避免它,並不難。 (在application_start中解析並使用已解析的依賴項進行初始化,而不是在初始化時提供解析器。) – 2014-09-02 15:52:39

+0

問題是關於將靜態類注入靜態類。這涉及如何將非靜態實例注入靜態類。 這看起來像是對以前的回答中的以下陳述的迴應:「同樣很難將任何東西注入靜態類」 – 2015-05-11 15:25:17

+0

對於像記錄器這樣簡單的事情,這看起來過於複雜。 – rolls 2017-04-30 03:34:29

0

我不確定記錄器是如何工作的,但通常您可以使用RequestService來獲取您的實例。例如在抽象類中:

this.HttpContext.RequestServices.GetService(typeof(YOUR_SERVICE)); 

對於控制器,您可以訪問HttpContext。

第二種方式是在啓動,在那裏你可以做到這一點使用它,例如:

serviceCollection.AddScoped(typeof(ICmsDataContext), typeof(TDbContext)); 

其中serviceCollection是IServiceCollection在DOTNET核心。

希望它有幫助。

1

這是一個非常簡單的方法來「注入」靜態記錄器的功能。

public static class Logger 
{ 
    private static Action<string, Exception> _logError; 
    public static bool Initialised; 

    public static void InitLogger(Action<string, Exception, bool> logError) 
    { 
     if(logError == null) return; 
     _logError = logError 
     Initialised = true; 
    } 

    public static void LogError(string msg, Exception e = null) 
    { 
     if (_logError != null) 
     { 
      try 
      { 
       _logError.Invoke(msg, e); 
      } 
      catch (Exception){} 
     } 
     else 
     { 
      Debug.WriteLine($"LogError() Msg: {msg} Exception: {e}"); 
     } 
    } 
} 

public class MainViewModel 
{ 
    public MainViewModel() 
    { 
     //Inject the logger so we can call it globally from anywhere in the project 
     Logger.InitLogger(LogError); 
    } 
    public void LogError(string msg, Exception e = null) 
    { 
     //Implementation of logger 
    } 
}