.net 在Log4net中使用包装类时如何记录方法名

.net 在Log4net中使用包装类时如何记录方法名,.net,log4net,.net,Log4net,我正在为log4.net实现一个自定义XML格式化程序 public class ISDSApplicationEventsLayout : XmlLayoutBase { protected override void FormatXml(...) { //Location Info writer.WriteStartElement("Method"); writer.WriteString(**loggingEvent.Loc

我正在为log4.net实现一个自定义XML格式化程序

public class ISDSApplicationEventsLayout : XmlLayoutBase
{
    protected override void FormatXml(...)
    {
        //Location Info 
        writer.WriteStartElement("Method");
        writer.WriteString(**loggingEvent.LocationInformation.MethodName * *);
        writer.WriteEndElement();
    }
}
问题是。。。现在,当我从日志包装器类调用log方法时。。。称为日志记录

public static void logEvent(string message)
{
    log.Info(isdsLog); 
}
我得到输出

  <Method>logEvent</Method>
logEvent
如何可能将调用logEvent的方法名而不是logEvent作为方法名

多谢各位

问题更新:

如果上面这看起来有点复杂-我真正想问的是:如何保持在log4net中调用包装日志函数的方法的上下文

例如。。。方法doWork()。。。调用->日志包装器-->调用log4net


如何使methodname=doWork和NOT logging wrapper函数……

我认为用现成的log4net很难解决这个问题。如果我们查看中的ILog.Info方法,您正在调用:

    virtual public void Info(object message) 
    {
        Logger.Log(ThisDeclaringType, m_levelInfo, message, null);
    }
记录消息时,log4net将遍历当前调用的堆栈跟踪,以找到启动日志操作的方法。为此,Log4net使用“ThisDeclaringType”类型作为搜索边界,选择该类型中的第一个调用“over”作为启动方法


在您的例子中,遇到的第一个方法是logEvent方法。如果您丢弃logEvent包装器并直接使用日志记录方法,您将获得所需的信息。

实际上,您可以使用现成的log4net轻松解决此问题。包装器可以调用Logger.Log并将包装器类的类型作为第一个参数传递。因此,您的包装可能如下所示:

public class MyLog4NetWrapper
{
  ILog log = LogManager.GetLogger("WhateverYourLoggerNameIs");

  public void logEvent(string message) 
  {     
    log.Logger.Log(typeof(MyLog4NetWrapper), LogLevel.Info, message, null);
  } 
}
当log4net记录消息时,它将遍历调用堆栈,直到到达一个方法,该方法的声明类型等于作为Log方法的第一个参数传入的类型。堆栈上的下一个方法是实际的调用站点


至于包装log4net记录器,我不确定是否建议创建一个静态包装器类。主要问题是,app.config文件中只能有一个可配置的记录器。换句话说,您将无法从代码的不同部分独立控制日志记录。如果您有类A和类B,并且都使用静态包装记录器,那么这两个类将以相同的级别进行日志记录。如果要打开A类的日志记录,关闭B类的日志记录,则无法执行此操作。

Wraper for log4net logger分3步执行:

添加对log4net包(NugetPackage)的引用

添加包装器类,确保调用log4net.Config.XmlConfigurator.Configure();在包装器类的静态构造函数中。这将从app.config加载所有配置

在app.config中添加log4net配置

请参见下面的示例包装器类

  public class Logger : ILogger
{
    private static readonly log4net.ILog log;


    static Logger()
    {
        log = log4net.LogManager.GetLogger(System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType);
        log4net.Config.XmlConfigurator.Configure();
    }

    public void Log(LogLevel logLevel, string message, params object[] args)
    {
        switch (logLevel)
        {
            case LogLevel.DEBUG: {
                    // log.Logger.Log helps logging actual method and the class which has called this method (Log(LogLevel logLevel, string message, params object[] args))
                    log.Logger.Log(typeof(Logger), log4net.Core.Level.Debug, string.Format(message, args), null);
                    break;
                }
            case LogLevel.INFO:
                {                       
                    log.Logger.Log(typeof(Logger), log4net.Core.Level.Info, string.Format( message, args) , null);
                    break;
                }
            case LogLevel.ERROR:
                {
                    log.Logger.Log(typeof(Logger), log4net.Core.Level.Error, string.Format(message, args), null);
                    break;
                }
            case LogLevel.WARN:
                {
                    log.Logger.Log(typeof(Logger), log4net.Core.Level.Warn, string.Format(message, args), null);
                    break;
                }
        }

    }

    public void LogException(LogLevel logLevel, Exception exception)
    {
        Log(logLevel, exception.ToString());
    }
}

实际上,可以创建一个记录器包装器来成功保存调用站点信息。请参阅我答案中的代码示例,了解实现此目的的一种方法。关键是将包装好的记录器的类型作为第一个参数传递给Log方法(而不是使用Info、Debug等方法)。好吧,如果你把你的代码改成
log.Logger.log(…)
至少:)@wageoghe:我一直遵循这个模式,它工作得很好,直到我以发布模式部署应用程序。这是“拯救”。有什么想法可以解决这个问题吗?可能是重复的