将结构图与 log4net 包装器一起使用

问题描述 投票:0回答:3

我有以下界面:

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

    }

我的想法是使用结构图来实例化 Log4netLogger 类,并使用执行日志记录的类的类型。但是,我一生都无法弄清楚如何将调用类的类型传递给 Structuremap,以便将其传递给日志记录实现的构造函数。任何有关如何做到这一点(或更好的方法)的建议将不胜感激。

inversion-of-control log4net structuremap
3个回答
26
投票

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

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

当存在对具体类型的依赖时,父类型 null 检查是必要的。

其余的是可选的 log4net 设置内容。

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


1
投票

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

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

也许可以引导 StructureMap 根据类型提供您想要的实例,但这假设您事先知道的类型数量有限。


1
投票

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

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

我实际上有一个结构映射的包装器(以避免将结构映射依赖项暴露给我的应用程序),如下所示:

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...");
© www.soinside.com 2019 - 2024. All rights reserved.