C# ILogger.Log方法去极化类型参数

C# ILogger.Log方法去极化类型参数,c#,log4net,C#,Log4net,当我想使用log4net提供的不同日志记录级别时,我发现我需要使用ILogger.Log方法,如下所示: void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception); 我们可以从通常的ILog引用中获得一个ILOGER引用来调用此方法,通常建议将此调用封装在扩展方法中。我们得到的结果如下: //typical log4net ILog reference pr

当我想使用log4net提供的不同日志记录级别时,我发现我需要使用ILogger.Log方法,如下所示:

void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception);
我们可以从通常的ILog引用中获得一个ILOGER引用来调用此方法,通常建议将此调用封装在扩展方法中。我们得到的结果如下:

//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);
}
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!
我注意到获取声明类型的反射调用看起来是多余的。在检索ILog引用时,我们已经将声明类型传递给GetLogger。为什么我们需要将另一个类型引用传递给方法日志,我们在从ILog引用检索到的ILOGER引用上调用该方法日志。更重要的是,扩展方法中的声明类型将是包含扩展方法的类。用Log4NetExtensions这样的类名记录所有跟踪日志是没有意义的。最后,反射被认为是昂贵的,尽管对当前方法的反射可能更便宜,但每次记录日志时调用反射代码听起来并不正确。所以我决定做一个测试:

//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);
生成的日志如下所示:

//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);
}
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的扩展方法。你能提出同样的建议吗?我错过什么了吗

以下问题的答案建议在扩展方法中使用声明类型:


您不应该像建议的那样创建扩展方法

因为ILog Logger是静态的,所以将其用作参数值没有多大意义。只需按以下方式使用Log4Net:

private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // that part was ok

public static void Trace(object message, Exception e)
{
   Logger.DebugFormat(message, e); // Use InfoFormat or something else if needed
}
如果只使用标准功能,只需直接调用DebugFormat()(或其他内容):

try {
  int i=7/0;
} catch (Exception e){
  Logger.ErrorFormat("Looks like you are not Jon Skeet",e); 
}
如果不添加任何内容,那么创建自己的“跟踪”方法是没有意义的


此外,(通常)在您记录某些内容时设置类型没有意义,但在初始化Logger时仅在类的顶部设置传递给LogManager的类型。GetLogger用来命名返回的Logger,这就是为什么所有日志调用都标记为“Foo.Program”

传递给
Logger.Log
的类型是“作为此调用的堆栈边界的方法的声明类型”,用于确定停止记录堆栈跟踪的位置-这是内部所需的,否则堆栈跟踪将包括log4net内部方法


您当然可以创建一个扩展方法,该方法将null作为
调用方TackBoundaryDeClaringType
,因为它在内部默认为
typeof(Logger)

扩展方法将由多个类使用,每个类都将以您建议的常用方式声明自己的ILog引用。另外,我希望使用Level.Trace记录消息,它没有ILog提供的标准方法。这是:“因为它将在内部默认为记录器的类型。”这就是我想要的。有推荐人吗?或者对如何测试有什么建议?log4net何时生成堆栈跟踪?当我传入异常时?但是异常不是有自己的堆栈跟踪吗?你说的异常有自己的堆栈跟踪是对的:log4net也是,但回想起来,这不是一个常见的用例-关于引用,我查看了源代码,