Is it a good practice to have logger as a singleton?

后端 未结 8 953
迷失自我
迷失自我 2020-12-12 12:08

I had a habit to pass logger to constructor, like:

public class OrderService : IOrderService {
     public OrderService(ILogger logger) {
     }
}

8条回答
  •  生来不讨喜
    2020-12-12 12:28

    A plain singleton is not a good idea. It makes it hard to replace the logger. I tend to use filters for my loggers (some "noisy" classes may only log warnings/errors).

    I use singleton pattern combined with the proxy pattern for the logger factory:

    public class LogFactory
    {
        private static LogFactory _instance;
    
        public static void Assign(LogFactory instance)
        {
            _instance = instance;
        }
    
        public static LogFactory Instance
        {
            get { _instance ?? (_instance = new LogFactory()); }
        }
    
        public virtual ILogger GetLogger()
        {
            return new SystemDebugLogger();
        }
    }
    

    This allows me to create a FilteringLogFactory or just a SimpleFileLogFactory without changing any code (and therefore complying to Open/Closed principle).

    Sample extension

    public class FilteredLogFactory : LogFactory
    {
        public override ILogger GetLogger()
        {
            if (typeof(ITextParser).IsAssignableFrom(typeof(T)))
                return new FilteredLogger(typeof(T));
    
            return new FileLogger(@"C:\Logs\MyApp.log");
        }
    }
    

    And to use the new factory

    // and to use the new log factory (somewhere early in the application):
    LogFactory.Assign(new FilteredLogFactory());
    

    In your class that should log:

    public class MyUserService : IUserService
    {
        ILogger _logger = LogFactory.Instance.GetLogger();
    
        public void SomeMethod()
        {
            _logger.Debug("Welcome world!");
        }
    }
    

提交回复
热议问题