2009-08-18 27 views
21

tengo una clase estática que llama a una clase Logger estática,La inyección de dependencia con un registrador estático, clase auxiliar estática

por ejemplo

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

¿Cómo me inyecto el registrador en mi clase estática?

Nota: He leído Dependency Injection in .NET with examples?, pero parece que usa un registrador de instancias.

Respuesta

24

No se puede inyectar un registrador estático. Tienes que cambiarlo a un registrador de instancias (si puedes) o envolverlo en un registrador de instancias (que llamará a la estática). También es bastante difícil inyectar algo a una clase estática (porque no se controla el constructor estático de ninguna manera) - es por eso que tiendo a pasar todos los objetos que quiero inyectar como parámetros.

21

Esto no es necesariamente así. Mientras su registrador estático expone un método para:

  • La inyección de las clases que desea inyectar o
  • La inyección de la DI de contenedores en una llamada al método apropiado antes de ejecutarlo (por ejemplo, en algo así como el asp .net global.asax Método Application_Start), entonces deberías estar bien.

Aquí hay un ejemplo. Tome la siguiente clase para DI:

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

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

Y aquí está nuestra clase estática que necesita un registrador:

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


    } 

Ahora, en un arranque global para su aplicación (en este caso, en mi global.asax .cs), puede crear instancias de su Contenedor DI, y luego entregarlo a su clase estática.

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

     } 

Y listo! Ahora está funcionando con DI en sus clases estáticas.

Espero que ayude a alguien. Estoy volviendo a trabajar una aplicación que utiliza MUCHAS clases estáticas, y hemos estado usando esto con éxito desde hace un tiempo.

+5

Me parece más a la resolución de dependencia que a la inyección de dependencia. La clase estática ahora tiene conocimiento del marco de dependencia. Pero no sería difícil adaptarlo para evitarlo. (Resolver en application_start e inicializar con dependencias resueltas, en lugar de suministrar el resolver en la inicialización). –

+0

La pregunta es acerca de cómo inyectar una clase estática en una clase estática. Se trata de cómo inyectar una instancia no estática en una clase estática. Esto parece una respuesta a la siguiente declaración en la respuesta anterior: "También es bastante difícil inyectar algo a una clase estática" –

+0

Esto parece demasiado complejo para algo tan simple como un registrador. – rolls

0

No estoy seguro de cómo funciona Logger, pero en general puede usar RequestService para obtener su instancia. Por ejemplo, en la clase abstracta:

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

Es posible para el regulador, donde se puede acceder a HttpContext.

La segunda manera es usarlo por ejemplo en de inicio, donde se puede hacer esto:

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

donde serviceCollection es IServiceCollection en Core dotnet.

Espero que haya sido de ayuda.

1

Esta es una forma muy simple de "inyectar" la funcionalidad de un registrador estático.

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