配置log4net记录器以匹配泛型类

时间:2013-03-13 19:07:10

标签: c# .net generics log4net

我想在我的应用程序中配置一个类来记录调试级别,所以我正在尝试为该类设置一个特定的记录器。但是,它没有改变到调试级别,我怀疑这是因为该类是通用的。我找到了通用类型的some examples配置,所以它看起来很可能,但它对我不起作用。

<root>
  <level value="INFO" />
  <appender-ref ref="OutputDebugStringAppender"/>
</root>
<logger name="MyCompany.MyGenericClass`1">
  <level value="DEBUG"/>
</logger>

以下是我在泛型类中声明我的记录器的方法。

public abstract class MyGenericClass<T> : IDisposable where T : class
{
    private static ILog _log = LogManager.GetLogger(typeof(MyGenericClass<T>));

3 个答案:

答案 0 :(得分:3)

看起来有two ways to get the class name,其中一个在记录器中配置起来要容易得多。

如果您将我的记录器声明更改为:

public abstract class MyGenericClass<T> : IDisposable where T : class
{
    private static ILog _log = LogManager.GetLogger(
        System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

然后我的原始配置将起作用:

<root>
  <level value="INFO" />
  <appender-ref ref="OutputDebugStringAppender"/>
</root>
<logger name="MyCompany.MyGenericClass`1">
  <level value="DEBUG"/>
</logger>

听起来`1指的是该类型的通用参数的数量,但我不确定。

如果您使用我的原始记录器声明:

public abstract class MyGenericClass<T> : IDisposable where T : class
{
    private static ILog _log = LogManager.GetLogger(typeof(MyGenericClass<T>));

然后你需要使用这个丑陋的配置:

<logger name="MyCompany.MyGenericClass`1[[MyCompany.MyParameterClass, MyLibrary, Version=1.2.0.0, Culture=neutral, PublicKeyToken=65af8642211d1afa]]">
  <level value="DEBUG"/>
</logger> 

第二个选项还意味着您需要为泛型类的每个参数类型提供单独的配置条目。

答案 1 :(得分:2)

我知道这有点晚了,但我遇到了同样的问题...

使用

LogManager.GetLogger(typeof(MyGenericClass<T>).ToString())

这适用于cfg,如下所示:

<logger name="MyCompany.MyGenericClass`1[MyCompany.MyParameterClass]">
  <level value="DEBUG"/>
</logger>

更短,没有版本号,简化了更新。另请注意,泛型类型定义中只有一组方括号,而不是通过Type的解决方案中的两个方括号。

答案 2 :(得分:0)

来自Java(因此非常了解log4xx范式),我看不出为什么日志输出应该打印任何通用类信息。对于通用基类的记录器名称,知道哪个派生确切地发出日志输出并不重要。

请注意,使用类名作为记录器名称只是一种约定。您可以使用其他任意字符串作为记录器名称。而且-当然-也是使用点分隔符和记录器名称的任意自己的记录器层次结构。

所以我写了一个LoggerName实用程序(说实话,我受this post的启发):

    public static string ClassNameForLogger(Type t)
    {
        if (t.IsGenericTypeDefinition || t.IsGenericType)
        {
            StringBuilder b = new StringBuilder();
            b.Append(t.Namespace).Append('.');

            int offset = t.Name.IndexOf('`');

            if (offset > 0)
            {
                b.Append(t.Name.Substring(0, offset));
            }
            else
            {
                b.Append(t.Name);
            }

            return b.ToString();
        }

        return t.FullName;
    }

并以此方式使用它:

public abstract class MyGenericClass<T>
{
    private static readonly ILog log = LogManager.GetLogger(LoggerUtil.ClassNameForLogger(typeof(MyGenericClass<T>)));

传递记录器名称为

<MyNamespace>.MyGenericClass