首页 文章

如何使用依赖注入的log4net

提问于
浏览
75

我试图找出log4net与依赖注入框架的正确模式和用法 .

Log4Net使用ILog接口但需要我调用

LogManager.GetLogger(Reflection.MethodBase.GetCurrentMethod().DeclaringType)

在我需要记录信息的每个类或方法中 . 这似乎违背了IoC原则并让我使用Log4Net .

我应该以某种方式在某处放置另一层抽象?

此外,我需要记录自定义属性,如当前用户名,如下所示:

log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;

我如何封装它,以便我不必记住每次都这样做并仍然保持当前记录的方法 . 我应该做这样的事情还是我完全错过了标记?

public static class Logger
{
    public static void LogException(Type declaringType, string message, Exception ex)
    {
        log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;
        ILog log = LogManager.GetLogger(declaringType);
        log.Error(message, ex);
    }
}

4 回答

  • 61

    我是如何创建自己的接口的,并且有一个使用Log4Net的接口的类实现,并注入了该类 . 通过这种方式,您不会与Log4Net绑定...您可以为新的 Logger 创建另一个类并注入该类 .

  • 2

    如果您真的担心有多个 Logger ,您可以随时声明一个全局 Logger 并调用它来满足您的所有记录需求 . 这样做的缺点是您失去了识别发出日志的类的内置功能,但您也可以将自己的自定义消息注入日志以识别类 .

    这取决于您希望日志记录的强大程度 . 您也可以简单地将 Logger 放在主类中,让所有未处理的异常冒泡到它以进行记录 .

  • 2

    我想你在这里看不到树林 . ILog和LogManager是一个轻量级的façade,几乎是1:1相当于Apache commons-logging,并且实际上并没有将你的代码耦合到log4net的其余部分 .

    <rant>
    我还发现,几乎总是当有人在log4net周围创建一个MyCompanyLogger包装器时,他们会错过这一点,并且会丢失框架的重要且有用的功能,丢弃有用的信息,甚至使用简化的ILog接口也会失去性能提升,或以上所有 . 换句话说, wrapping log4net to avoid coupling to it is an anti-pattern .
    </rant>

    如果您觉得需要注入它,请通过属性访问您的 Logger 实例以启用注入,但以旧式方式创建默认实例 .

    至于在每条日志消息中包含上下文状态,您需要添加一个 ToString() 解析为您正在查找的内容的全局属性 . 例如,对于当前堆大小:

    public class TotalMemoryProperty
    {
        public override string ToString()
        {
            return GC.GetTotalMemory(false).ToString();
        }
    }
    

    然后在启动期间将其插入:

    GlobalContext.Properties["TotalMemory"] = new TotalMemoryProperty();
    
  • 2

    另一种方法是连接log4net ILog接口容器注册序列,如下所示:(在下面的ASP.NET上下文中使用Castle作为示例)

    container.Register(Component.For<ILog>().LifeStyle
        .PerWebRequest.UsingFactoryMethod(() => LogManager.GetLogger(
        MethodBase.GetCurrentMethod().DeclaringType)));
    

    只需构造函数 - 只要你需要就注入ILog .

相关问题