Log4Net 不正确的转换模式与通用类和精度参数



C# 日志记录框架 log4net 在具有精度参数的转换模式中使用时,似乎错误地处理了所有记录器和追加程序中的泛型类名(例如%logger{1})。因为我根本找不到任何相关的问题/疑问,所以我决定发布该问题的详细概要,希望有人知道修复/解决方法。

例如,具有上述会话模式的泛型类DiskSaviourHook<T>应该产生DiskSaviourHook,而是输出0, Culture=neutral, PublicKeyToken=null]](这显然是错误的)。经过进一步调查,我发现这是因为log4net解析器在与{1}精度参数一起使用时只寻找最后一个点。

更具体地说,记录器名称Sigma.Core.Training.Hooks.Saviors.DiskSaviorHook'1[[Sigma.Core.Architecture.INetwork, Sigma.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]被视为与任何其他记录器名称一样,尽管它是通用的并且具有比平时更多的点(版本的最后一个点的处理方式与实际类的最后一个点一样)。此问题是否有任何已知的修复/解决方法?

转换模式工作正常。在 log4net 中,记录器名称是分层的,层次结构的级别由句点分隔。这恰好与类在命名空间中的命名方式非常一致,因此将类名用于记录器名称是一种普遍的做法(从而可以轻松地为整个命名空间配置日志记录)。如此普遍,以至于log4net对其具有重载:LogManager.GetLogger(Type)实现为LogManager.GetLogger(Assembly.GetCallingAssembly(), Type.FullName)

不幸的是,这不适用于泛型。泛型类型有一个包含其类型参数的FullName,这会破坏 log4net 使用的层次结构。当然,您仍然可以拥有一个名为Sigma.Core.Training.Hooks.Saviors.DiskSaviorHook'1[[Sigma.Core.Architecture.INetwork, Sigma.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]的记录器,但就log4net而言,它具有特别丑陋的层次结构,其中包括DiskSaviorHook'1[[Sigma等组件。层次结构纯粹是语法的,而不是基于分析实际的类名。事实上,对记录器使用类名只是一种约定,尽管是一种有用的约定。

如果我是log4net开发人员并且不关心向后兼容性,我会LogManager.GetLogger(Type)实现为LogManager.GetLogger(Assembly.GetCallingAssembly(), Type.Namespace + Type.Name),它不会受到此问题的影响。但我不是,我也懒得打开一个问题。

对于客户端代码,有一个简单的解决方法。像这样替换代码:

static ILog log = LogManager.GetLogger(typeof(DiskSaviourHook<T>));

用这个:

static ILog log = LogManager.GetLogger(typeof(DiskSaviourHook<>));

或者这个:

static ILog log = LogManager.GetLogger(
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType
);

后者在文档中作为一段样板文件被提及,以获取类名而不提及它,并且它还将为泛型做"正确的事情"。(我仍然更喜欢简单地输入类名而不是反思。

最新更新