【问题标题】:c# log4net extensions wrong line and locationc#log4net扩展错误的行和位置
【发布时间】:2014-03-08 07:11:55
【问题描述】:

当我在我的 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);
            }
        }
    }
}

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

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

【问题讨论】:

  • 您能在此处添加您的扩展方法的代码吗?
  • 我更新了我的答案以包含一个扩展方法的示例,该方法确实维护了正确的呼叫站点信息。我不知道它是否对您有帮助,因为您已经使用了包装器,但我想我会传递它。

标签: c#-4.0 log4net extension-methods


【解决方案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);
    }
  }

【讨论】:

  • 那太糟糕了。我本来希望这样做的。不幸的是,我现在没有时间玩弄它来弄清楚发生了什么。
  • 包装类确实有效。我试图避免这么多的重构。
  • 标记为答案。可能是一种通过扩展来做到这一点的方法,但我创建了一个包装类。由于我几乎只使用扩展,将它们移动到包装类并删除“this ILog”和静态比我想象的要容易得多。
猜你喜欢
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 2022-08-18
相关资源
最近更新 更多