当在具有精确参数的转换模式中使用时,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]]
被视为任何其他记录器名称,尽管它是通用的并且具有比平常更多的点(版本的最后一个点的处理方式与实际类的最后一个点一样) 。这个问题是否有任何已知的修复/解决方法?
答案 0 :(得分:1)
转换模式运行正常。在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
);
后者在文档中被提及作为一个样板来获取类名而不提及它,它也将为泛型做“正确的事情”。 (我仍然喜欢简单地将自己的班级名称放在反思上。)