奇怪的log4net初始化行为

本文关键字:初始化 log4net | 更新日期: 2023-09-27 18:12:47

我遇到了一些奇怪的行为与log4net,不知道是否有人可以解释这个给我,我想了解更多的了解它。

在我的WPF App.xaml.cs OnStartup覆盖方法中,我有以下代码设置了用于日志记录的log4net属性:

// logLocation is a path to a subdir in the users' appdata roaming dir
log4net.GlobalContext.Properties["LogLocation"] = logLocation;
logger = LogManager.GetLogger(typeof(App));
logger.Info("OnStartup: " + string.Join(" ", e.Args));

我在创建任何其他记录器之前这样做(至少我是这样认为的)。

在我的配置文件中有以下行:

<file type="log4net.Util.PatternString" value="%property{LogLocation}" />

用于指定日志文件的位置。但是,我遇到了这样一种情况,这种情况失败了——导致将日志写入执行目录中的文件名为"(null)"。

似乎是下面的伪代码导致了这个问题,它在上面代码之后的同一个OnStartup方法中:

AnyClass ac = new AnyClass();
ac.NoOp();

其中AnyClass有一个logger实例化如下:

private static ILog logger = LogManager.GetLogger(typeof(AnyClass));

我使用伪代码的原因是,我可以在任何我实例化并调用方法的类上复制这种行为。如果没有调用任何方法,则日志记录路径按预期工作。

有几点需要注意:

  1. 当我在调试或发布模式下在调试器中运行它时,它会起作用。这个错误只在我直接运行exe或通过'Start Without Debugging'时出现。
  2. 如果记录器不是静态定义的,那么问题就消失了
  3. 如果我添加一个静态构造函数到AnyClass,那么问题就消失了,即:

    静态AnyClass() {}

  4. 如果我将ac.NoOp()的调用移动到次要方法,由OnStartup调用-错误消失

所以,回顾一下,这个错误仅仅是由使用静态日志初始化实例化一个类,并在OnStartup方法中调用该类的一个方法引起的。

我有几种方法来解决这个问题,但我想了解更多,以了解为什么会发生这种情况。

奇怪的log4net初始化行为

我认为ac.NoOp();正在创建一个新实例的记录器和新实例不知道什么是PatternString的值。因此使用null

请参考此链接

public static Logger getLogger(String name)
Retrieve a logger named according to the value of the name parameter. 
If the named logger already exists, then the existing instance will be returned. 
Otherwise, **a new instance** is created.