如何使用依赖注入的log4net

Mic*_*cah 77 log4net design-patterns dependency-injection

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

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

LogManager.GetLogger(Reflection.MethodBase.GetCurrentMethod().DeclaringType)
Run Code Online (Sandbox Code Playgroud)

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

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

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

log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;
Run Code Online (Sandbox Code Playgroud)

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Jef*_*tin 62

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

<rant>
我还发现,几乎总是当有人在log4net周围创建一个MyCompanyLogger包装器时,他们会错过这一点,并且会丢失框架的重要且有用的功能,丢弃有用的信息,甚至使用简化的ILog接口也会失去性能提升,或以上所有.换句话说,包装log4net以避免与它耦合是一种反模式.
</rant>

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

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

public class TotalMemoryProperty
{
    public override string ToString()
    {
        return GC.GetTotalMemory(false).ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

GlobalContext.Properties["TotalMemory"] = new TotalMemoryProperty();
Run Code Online (Sandbox Code Playgroud)

  • +1出来然后说它糟糕的juju这样做. (11认同)
  • 你的咆哮远离这里.这家伙问的是如何将ILog的实例注入到容器内的对象中.有很多理由这样做. (5认同)
  • @JeffreyHantin在你看来,这可能是一种反模式,但我发现那里有很多意见,因为有工程师编写代码.我当然认为:) (3认同)