如何在dependency injection中使用log4net

我试图找出什么是正确的模式和使用log4net是dependency injection框架。

Log4Net使用ILog接口,但需要我打电话

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

在每个类或方法中,我需要logging信息。 这似乎违背了IoC的原则,并配合我使用Log4Net。

我应该不知何故把某个地方的另一层抽象层?

此外,我需要logging像当前用户名这样的自定义属性:

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

我怎么能封装这个,所以我不必记得每次都这样做,仍然保持当前正在logging的方法。 我应该做这样的事情还是我完全错过了标记?

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

我想你没有看到这里的树林。 ILog和LogManager是一个轻量级的外观,几乎相当于Apache commons-logging的1:1,实际上并没有将你的代码连接到log4net的其余部分。

<rant>
我也发现, 几乎总是当有人创build一个围绕log4net的MyCompanyLogger包装,他们错过了这一点,将失去框架的重要和有用的function,扔掉有用的信息,甚至使用简化的ILog接口,或以上全部。 换句话说, 包装log4net避免耦合到它是一个反模式
</rant>

如果您觉得需要注入它,可以通过一个属性使您的logging器实例可访问,以启用注入,但以旧式方式创build默认实例。

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

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

然后在启动过程中插入:

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

我是如何创build自己的接口,并有一个类实现了使用Log4Net的接口,并注入了该类。 这样你就不会被绑定到Log4Net …你可以为一个新的logging器创build另一个类并注入这个类。

如果你真的关心有多个logging器,你总是可以声明一个全局logging器,并为你所有的logging需求调用它。 这样做的缺点是你失去了识别日志发布类的内置function,但是你也可以在日志中注入自定义的消息来识别类。

这取决于你想要logging的强大程度。 您也可以简单地把logging器放在主类上,让所有未处理的exception冒泡到logging。

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

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

只需要构造函数注入ILog。