代码之家  ›  专栏  ›  技术社区  ›  Chris

将structuremap与log4net包装一起使用

  •  10
  • Chris  · 技术社区  · 15 年前

    我有以下界面:

    public interface ILogger
    {
        void Debug(string message, params object[] values);
        void Info(string message, params object[] values);
        void Warn(string message, params object[] values);
        void Error(string message, params object[] values);
        void Fatal(string message, params object[] values);
    }
    

    以及以下实施:

    public class Log4netLogger : ILogger
    {
        private ILog _log;
    
        public Log4netLogger(Type type)
        {
            _log = LogManager.GetLogger(type);
        }
    
        public void Debug(string message, params object[] values)
        {
            _log.DebugFormat(message, values);
        }
    
        // other logging methods here...
    
    }
    

    我的想法是使用structuremap使用执行日志记录的类的类型来实例化log4netlogger类。但是,在我的一生中,我无法弄清楚如何将调用类的类型传递给structuremap,以便将其传递给日志实现的构造函数。关于如何做到这一点(或更好的方法)的任何建议都将是最受欢迎的。

    3 回复  |  直到 15 年前
        1
  •  1
  •   Phil Sandler    15 年前

    如果类型参数是特定于上下文的,我认为它不会如图所示工作。如果需要在构造函数中传递特定于上下文的内容,则可能需要创建一个工厂接口和实现,该接口和实现返回ilogger的实例:

    public interface ILoggerFactory
    {
        ILogger Create(Type type);   
    }
    
    public class LoggerFactory : ILoggerFactory
    {
        public ILogger Create(Type type)
        {
            return new Log4netLogger(type);
        }
    }
    

    可以根据类型引导结构映射来提供所需的实例,但前提是预先知道的类型数量有限。

        2
  •  24
  •   KevM    15 年前

    我们在log4net周围使用类似的ilogger包装器,通常使用构造函数注入。我们使用拦截器作为负责创建记录器的工厂方法。这里是日志设置的典型注册表。

    public class CommonsRegistry : Registry
    {
        public CommonsRegistry()
        {
            For<ILogger>()
                .AlwaysUnique()
                .TheDefault.Is.ConstructedBy(s =>
                {
                    if (s.ParentType == null)
                        return new Log4NetLogger(s.BuildStack.Current.ConcreteType);
    
                    return new Log4NetLogger(s.ParentType);
                });
    
            var applicationPath = Path.GetDirectoryName(Assembly.GetAssembly(GetType()).Location);
            var configFile = new FileInfo(Path.Combine(applicationPath, "log4net.config"));
            XmlConfigurator.ConfigureAndWatch(configFile);
        }
    }
    

    当依赖于具体类型时,需要进行父类型空检查。

    其余是可选的log4net安装工具。

    我喜欢这个设置的一件事是能够使用空记录器进行单元测试。

        3
  •  1
  •   Chris    15 年前

    我真的需要改掉回答我自己问题的习惯,但对于遇到这个问题的人来说,答案是这样的。

    return ObjectFactory.With(type).GetInstance<T>();
    

    我实际上有一个到structuremap的包装(为了避免向我的应用程序公开structuremap依赖项),如下所示:

    public static class ServiceManager
    {
        public static T Get<T>()
        {
            return ObjectFactory.GetInstance<T>();
        }
    
        public static T Get<T>(Type type)
        {
            return ObjectFactory.With(type).GetInstance<T>();
        }
    }
    

    在代码中的任何时候我需要一个记录器,我调用以下代码:

    ServiceManager.Get<ILogger>(GetType()).Info("Logging page view...");