Dependency injection with a static logger, static helper class

前端 未结 4 741
[愿得一人]
[愿得一人] 2020-11-30 04:10

I have a static class which calls a static Logger class,

e.g

static class DoesStuffStatic
{
  public static void DoStuff()
  {
    try
    {
      //         


        
相关标签:
4条回答
  • 2020-11-30 04:21

    This is not necessarily so. As long as your static logger exposes a method for:

    • Injection of the classes you WANT injected, or
    • Injection of the DI Container in an appropriate method call prior to running it (say in something like the asp.net global.asax Application_Start method), then you should be fine.

    Here's an example. Take the following class for DI:

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

    And here's our static class which needs a logger:

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

    Now, in a global startup for your app (in this case, in my global.asax.cs), you can instantiate your DI Container, then hand that off to your static class.

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

    And presto! You are now up and running with DI in your static classes.

    Hope that helps someone. I am re-working an application which uses a LOT of static classes, and we've been using this successfully for a while now.

    0 讨论(0)
  • 2020-11-30 04:30

    I'm not sure how Logger works, but generally you can use RequestService to get your instance. For example in abstract class:

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

    It is possible for controller, where you can access to HttpContext.

    The second way is use it for example in Startup, where you can do this:

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

    where serviceCollection is IServiceCollection in dotnet Core.

    Hope it helped.

    0 讨论(0)
  • 2020-11-30 04:35

    You can't inject a static logger. You have to either change it to an instance logger (if you can), or wrap it in an instance logger (that will call the static). Also it is fairly hard to inject anything to a static class (because you don't control the static constructor in any way) - that's why I tend to pass all the objects I want to inject as parameters.

    0 讨论(0)
  • 2020-11-30 04:36

    This is a very simple way to "inject" the functionality of a static logger.

    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
        }
    }
    
    0 讨论(0)
提交回复
热议问题