Log4Net不正确的转换模式与泛型类和精度论证

时间:2017-04-13 21:08:38

标签: c# 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]]被视为任何其他记录器名称,尽管它是通用的并且具有比平常更多的点(版本的最后一个点的处理方式与实际类的最后一个点一样) 。这个问题是否有任何已知的修复/解决方法?

1 个答案:

答案 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
);

后者在文档中被提及作为一个样板来获取类名而不提及它,它也将为泛型做“正确的事情”。 (我仍然喜欢简单地将自己的班级名称放在反思上。)