2

我想在我的应用程序中配置一个类以在调试级别进行日志记录,因此我正在尝试为该类设置一个特定的记录器。不过,它并没有更改为调试级别,我怀疑这是因为该类是通用的。我找到了一些泛型类型的配置示例,所以看起来是可能的,但它对我不起作用。

<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>));
4

3 回答 3

3

看起来有两种获取类名的方法,其中一种更容易在记录器中配置。

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

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> 

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

于 2013-03-13T19:07:09.700 回答
3

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

采用

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

这将适用于如下所示的 cfg:

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

更短且不涉及版本号,从而简化了更新。另请注意,泛型类型定义中只有一组方括号,而不是通过Type.

于 2018-05-25T14:01:48.143 回答
0

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

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

所以我写了一个小 LoggerName 实用程序(老实说,我受到这篇文章的启发):

    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
于 2020-12-09T10:20:53.960 回答