2009-08-18 17 views
21

ho una classe statica che definisce una classe Logger statica,Dependency Injection con un registratore statica, classe di supporto statica

es

static class DoesStuffStatic 
{ 
    public static void DoStuff() 
    { 
    try 
    { 
     //something 
    } 
    catch(Exception e) 
    { 
     //do stuff; 
     Logger.Log(e); 
    } 
    } 
} 

static class Logger 
{ 
    public static void Log(Exception e) 
    { 
    //do stuff here 
    } 
} 

Come faccio a iniettare il Logger nella mia classe statica?

Nota: ho letto Dependency Injection in .NET with examples?, ma questo sembra utilizzare un registratore di istanze.

risposta

24

Non è possibile iniettare un registratore statico. Devi cambiarlo in un logger di istanze (se puoi) oppure avvolgerlo in un logger di istanze (che chiamerà static). Inoltre è abbastanza difficile iniettare qualcosa in una classe statica (perché non si controlla in alcun modo il costruttore statico): è per questo che tendo a passare tutti gli oggetti che voglio iniettare come parametri.

21

Questo non è necessariamente così. Finché il vostro registratore statico espone un metodo per:

  • Iniezione delle classi che si desidera iniettato, o
  • iniezione del DI Container in una chiamata di metodo appropriato prima di eseguirlo (voce in qualcosa di simile al asp .net global.asax Application_Start metodo), quindi si dovrebbe andare bene.

Ecco un esempio. Prendere la seguente classe per DI:

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

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

Ed ecco la nostra classe statica che ha bisogno di un registratore:

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); 
     } 


    } 

Ora, in una startup globale per la vostra applicazione (in questo caso, a mio global.asax .cs), è possibile creare un'istanza del contenitore DI, quindi consegnarlo alla classe statica.

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"); 

     } 

E presto! Ora sei attivo e funzionante con DI nelle tue classi statiche.

La speranza che aiuta qualcuno. Sto rielaborando un'applicazione che utilizza un sacco di classi statiche, e lo stiamo usando con successo da un po 'di tempo.

+5

Mi sembra più simile alla risoluzione delle dipendenze dell'iniezione di dipendenza. La classe statica ora ha conoscenza del framework delle dipendenze. Ma non sarebbe difficile adattarlo per evitarlo. (Risolvere in application_start e inizializzare con dipendenze risolte, anziché fornire il resolver durante l'inizializzazione.) –

+0

La domanda riguarda l'iniezione di una classe statica in una classe statica. Questo riguarda come iniettare un'istanza non statica in una classe statica. Questa sembra una risposta alla seguente affermazione nella risposta precedente: "Inoltre è abbastanza difficile iniettare qualcosa in una classe statica" –

+0

Questo sembra troppo complesso per qualcosa di semplice come un logger. – rolls

0

Non so come funziona Logger, ma in generale è possibile utilizzare RequestService per ottenere l'istanza. Ad esempio, in classe astratta:

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

E 'possibile per il controller, dove è possibile accedere a HttpContext.

Il secondo modo è usarlo per esempio in avvio, dove si può fare questo:

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

dove serviceCollection è IServiceCollection in dotnet Nucleo.

Spero che abbia aiutato.

1

Questo è un modo molto semplice per "iniettare" la funzionalità di un registratore statico.

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 
    } 
} 
Problemi correlati