我遇到了一些与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具有如下实例化的记录器:
private static ILog logger = LogManager.GetLogger(typeof(AnyClass));
我使用伪代码的原因是,我可以使用我实例化的任何类复制此行为并调用方法。如果没有调用方法,则日志记录路径按预期工作。
有几点需要注意:
如果我向AnyClass添加一个静态构造函数,那么问题就会消失,即:
static AnyClass(){}
如果我将对ac.NoOp()的调用移动到OnStartup调用的辅助方法 - 错误就会消失。
因此,回顾一下,错误只是通过使用静态记录器初始化实例化一个类,并在OnStartup方法中调用该类的方法引起的。
我有几种方法可以解决这个问题,但我希望了解更多,以了解为什么会发生这种情况。
答案 0 :(得分:0)
我认为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.