2009-08-18 12 views
21

Mam statyczną klasę, która wywołuje statyczne klasy Logger,Dependency Injection ze statycznym rejestratora, statyczne klasy pomocnika

np

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

Jak mogę wstrzyknąć Logger do mojego statycznych klasy?

Uwaga: Przeczytałem Dependency Injection in .NET with examples?, ale wydaje się, że używa się rejestratora instancji.

Odpowiedz

24

Nie można wstrzyknąć statycznego rejestratora. Musisz albo zmienić go na rejestrator instancji (jeśli możesz), albo zawinąć go w rejestratorze instancji (który wywoła statyczny kod). Również dość trudno jest wstrzyknąć cokolwiek do klasy statycznej (ponieważ nie kontrolujesz konstruktora statycznego w jakikolwiek sposób) - dlatego zazwyczaj przekazuję wszystkie obiekty, które chcę wstrzyknąć jako parametry.

21

To niekoniecznie musi tak być. Dopóki statyczny rejestrator naraża metodę:

  • wstrzyknięciu klas chcesz wtryskiwanego lub
  • wtrysk kontenera DI w odpowiednim wywołanie metody przed uruchomieniem go (powiedzmy w czymś takim jak asp .net global.asax Application_Start), powinieneś być w porządku.

Oto przykład. Podjąć następujące klasy dla DI:

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

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

A oto nasza klasa statyczna, która potrzebuje Rejestrator:

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


    } 

Teraz w globalnym uruchamiania dla aplikacji (w tym przypadku, moim global.asax .cs), możesz utworzyć instancję DI Container, a następnie przekazać ją do swojej klasy statycznej.

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

     } 

I presto! Jesteś teraz uruchomiony z DI w swoich klasach statycznych.

Nadzieję, że pomaga komuś. Ponownie pracuję nad aplikacją, która korzysta z DUŻYCH klas statycznych i od pewnego czasu używamy tego z powodzeniem.

+5

Wygląda mi to bardziej na rozwiązywanie zależności niż wstrzyknięcie zależności. Klasa statyczna ma teraz wiedzę o strukturze zależności. Ale nietrudno go przystosować, aby tego uniknąć. (Rozwiązuj w app_start i zainicjuj z rozwiązanymi zależnościami, zamiast dostarczać resolver podczas inicjalizacji.) –

+0

Pytanie dotyczy wstrzykiwania klasy statycznej do klasy statycznej. Zajmuje się tym, jak wstrzyknąć niestatyczną instancję do klasy statycznej. To wygląda jak odpowiedź na następujące stwierdzenie w poprzedniej odpowiedzi: "Również jest dość trudno wstrzyknąć cokolwiek do klasy statycznej" –

+0

To wydaje się zbyt skomplikowane dla czegoś tak prostego, jak rejestrator. – rolls

0

Nie jestem pewien, jak działa program Logger, ale ogólnie można użyć usługi RequestService, aby pobrać instancję. Na przykład w klasie abstrakcyjnej:

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

Jest to możliwe dla kontrolera, w którym można uzyskać dostęp do HttpContext.

Drugim sposobem jest wykorzystanie go na przykład w Uruchomienie, gdzie można to zrobić:

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

gdzie serviceCollection jest IServiceCollection w dotnet Core.

Mam nadzieję, że pomogło.

1

To bardzo prosty sposób na "wstrzyknięcie" funkcjonalności statycznego programu rejestrującego.

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 
    } 
} 
Powiązane problemy