【发布时间】:2015-05-30 00:53:54
【问题描述】:
当我想使用 log4net 提供的不同日志级别时,我发现我需要使用 ILogger.Log 方法,它看起来像这样:
void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception);
我们可以从我们常用的 ILog 引用中获取 ILogger 引用来调用此方法,通常建议将此调用包装在扩展方法中。我们得到的是:
//typical log4net ILog reference
private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
//suggested extension method
public static void Trace(this ILog logger, object message, Exception e)
{
logger.Logger.Log(MethodBase.GetCurrentMethod().DeclaringType, log4net.Core.Level.Trace, message, e);
}
我注意到获取声明类型的反射调用看起来是多余的。当我们检索 ILog 引用时,我们已经将声明类型传递给了 GetLogger。为什么我们需要将另一个类型引用传递给方法 Log,我们正在从 ILog 引用中检索到的 ILogger 引用上调用该方法。更重要的是,扩展方法中的声明类型将是包含扩展方法的类。使用 Log4NetExtensions 之类的类名记录所有 Trace 日志是没有意义的。最后,反射应该是昂贵的,即使在当前方法上反射可能更便宜,每次我们记录时调用反射代码听起来都不对。所以我决定做一个测试:
//I just created a logger
var logger = logManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
//and then I called Log with different type parameters
logger.Logger.Log(MethodBase.GetCurrentMethod().DeclaringType, log4net.Core.Level.Info, "hello!", null);
logger.Logger.Log(logger.GetType(), log4net.Core.Level.Info, "hello!", null);
logger.Logger.Log(null, log4net.Core.Level.Info, "hello!", null);
logger.Logger.Log(typeof(System.Console), log4net.Core.Level.Info, "hello!", null);
生成的日志如下所示:
INFO 2015-05-29 11:06:57,200 [9] Foo.Program - hello!
INFO 2015-05-29 11:06:57,207 [9] Foo.Program - hello!
INFO 2015-05-29 11:06:57,207 [9] Foo.Program - hello!
INFO 2015-05-29 11:06:57,207 [9] Foo.Program - hello!
所以,这个方法的类型参数似乎被忽略了。这是非常令人费解的。任何人都可以确认或否认这些结果吗?有谁知道为什么会这样?我打算为此参数创建带有 null 的扩展方法。你会建议同样的吗?我错过了什么吗?
以下问题的答案建议在扩展方法中使用声明类型:
Log4net creating custom levels
【问题讨论】: