Iniezione di dipendenza con un logger statico, class helper statica

Ho una class statica che chiama una class Logger statica,

per esempio

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 ad iniettare il Logger nella mia class statica?

Nota: ho letto Dependency Injection in .NET con esempi? , ma questo sembra usare un logger di istanze.

    Non è ansible 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 class 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.

    Non é necessariamente così. Finché il tuo logger statico espone un metodo per:

    • Iniezione delle classi che VUOI iniettate, o
    • Iniezione del contenitore DI in una chiamata di metodo appropriata prima di eseguirla (ad esempio in qualcosa come il metodo asp.net global.asax Application_Start), quindi si dovrebbe andare bene.

    Ecco un esempio. Prendi la seguente class 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 class statica che ha bisogno di un logger:

     public static class SomeStaticClass { private static IKernel _diContainer; private static ILogger _logger; public static void Init(IKernel dIcontainer) { _diContainer = dIcontainer; _logger = _diContainer.Get(); } public static void Log(string stringToLog) { _logger.Log(stringToLog); } } 

    Ora, in una startup globale per la tua app (in questo caso, nel mio global.asax.cs), puoi istanziare il tuo DI Container, quindi consegnarlo alla tua class statica.

     public class Global : Ninject.Web.NinjectHttpApplication { protected override IKernel CreateKernel() { return Container; } static IKernel Container { get { var standardKernel = new StandardKernel(); standardKernel.Bind().To(); 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.

    Spero che aiuti qualcuno. Sto rielaborando un’applicazione che utilizza un sacco di classi statiche, e lo stiamo usando con successo da un po ‘di tempo.

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

     public static class Logger { private static Action _logError; public static bool Initialised; public static void InitLogger(Action 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 } } 

    Non sono sicuro di come funziona Logger, ma in generale è ansible utilizzare RequestService per ottenere l’istanza. Ad esempio in class astratta:

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

    È ansible per il controller, in cui è ansible accedere a HttpContext.

    Il secondo modo è usarlo, ad esempio, in Startup , dove puoi fare questo:

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

    dove serviceCollection è IServiceCollection in dotnet Core.

    Spero che abbia aiutato.