c#log4net扩展名错误的行和位置

时间:2014-03-07 16:48:29

标签: c#-4.0 log4net extension-methods

当我在PatternLayout中使用%l或%L进行调试时,我得到扩展静态类的位置和该文件中的行号,而不是调用者的位置和行。任何标准记录方法都会产生正确的结果。有没有办法让扩展方法做到这一点?

我的部分Log4NetExtensions.cs

namespace Dashboard
{
    public static partial class Util
    {
        public static void SqlError(this ILog log, SqlException sqle)
        {
             if (log.IsDebugEnabled)
            {
                string[] names = Enum.GetNames(typeof(Dashboard.Models.Response.DashError.StandardErrors));
                int idx = Array.IndexOf(names, sqle.Message);
                if (idx > 0)
                {
                    log.Debug(sqle.Message);
                }
                else
                {
                    log.Error(sqle);
                }
            }
            else
            {
                log.Error(sqle);
            }
        }
    }
}

编辑: 根据我的回答,我将log.Error()和log.Debug更改为此但它仍然打印Util而不是调用者:

log.Logger.Log(typeof(Util), Level.Error, sqle.Message, sqle);

1 个答案:

答案 0 :(得分:1)

请参阅此处关于另一个问题的答案,了解如何在包装log4net时维护呼叫站点信息。

how to log method name when using wrapper class with Log4net

即使您正在编写扩展方法,您实际上也在包装log4net。该答案中描述的技术应该适用于扩展方法,也适用于包装器。您的解决方案应该是在您的包装器中使用Log方法而不是Info,Error等。作为Log方法的第一个参数,发送扩展方法静态类的类型。

您的扩展方法看起来像这样(未编译或测试):

namespace Dashboard
{
    public static partial class Util
    {
        public static void SqlError(this ILog log, SqlException sqle)
        {
             if (log.IsDebugEnabled)
            {
                string[] names = Enum.GetNames(typeof(Dashboard.Models.Response.DashError.StandardErrors));
                int idx = Array.IndexOf(names, sqle.Message);
                if (idx > 0)
                {
                    //Note that I am using the Logger member and then calling the Log method it.
                    log.Logger.Log(typeof(Util), LogLevel.Debug, sqle.Message, null);
                }
                else
                {
                    //Not sure about this call because you want to log only the exception.  Don't
                    //know if log4net will accept null as "message" parameter.
                    log.Logger.Log(typeof(Util), LogLevel.Error, null, sqle);
                }
            }
            else
            {
                //Not sure about this call because you want to log only the exception.  Don't
                //know if log4net will accept null as "message" parameter.
                log.Logger.Log(typeof(Util), LogLevel.Error, null, sqle);
            }
        }
    }
}

如果它不能正常工作,我想你会明白这个想法。

更新

FWIW,我把这个小样本放在一起,然后使用扩展方法记录呼叫站点所需的方法(主要):

  class Program
  {
    static void Main(string[] args)
    {
      var logger = LogManager.GetLogger("abc");
      ILogger ilog = logger.Logger;

      logger.Info("Hello");
      logger.InfoExt("Hello2");
    }
  }

  public static class Extensions
  {
    public static void InfoExt(this ILog logger, string message)
    {
      logger.Logger.Log(typeof(Extensions), Level.Info, message, null);
    }
  }