【问题标题】:log4net argument to LogManager.GetLoggerLogManager.GetLogger 的 log4net 参数
【发布时间】:2009-03-25 02:44:54
【问题描述】:

为什么大多数 log4net 示例通过这样做来获取类的记录器:

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

而不仅仅是传递 typeof(MyClass):

private static ILog logger = LogManager.GetLogger(typeof(MyClass));

除了第一个选项不需要您输入特定的类名之外,还有其他原因吗?

【问题讨论】:

    标签: log4net


    【解决方案1】:

    我想你已经找到了原因。我这样做是为了不用担心类名,只需将样板代码复制并粘贴到新类中即可。

    官方回答见:如何在静态块中获取类的全称?在log4net faq

    【讨论】:

    • 好的,它清除了,感谢那个链接,我以前没见过这个
    • 这是最古老的,但看看我的答案,以防你仍然将它粘贴为锅炉代码:)
    • 您确实节省了一点开发时间剪切和粘贴此代码。然而,调用“GetCurrentMethod()”而不是使用字符串常量或调用“typeof()”是有代价的。如果您将在代码的生命周期内调用该函数的次数与您输入类名所需的时间相加,我认为您只是在减慢代码速度而没有什么好处。
    • 您并没有像您想象的那样放慢速度,这是一个静态调用,因此每个应用程序域的每个类都有一个调用,例如如果你有 300 个类,那么在你的应用程序的生命周期内,你最多可以调用 300 次
    • 使用反射来获取类型名称是没有意义的,并且复制/过去是惰性的,并且会影响性​​能,所以为什么不只获取名称呢?!
    【解决方案2】:

    我是 NLog 用户,通常这归结为:

    var _logger = LogManager.GetCurrentClassLogger();
    

    你需要在 Log4Net 中进行反射似乎有点奇怪,所以我查看了 NLog 源代码,你瞧,这就是他们为你做的:

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static Logger GetCurrentClassLogger()
    {
        string loggerName;
        Type declaringType;
        int framesToSkip = 1;
        do
        {
    #if SILVERLIGHT
            StackFrame frame = new StackTrace().GetFrame(framesToSkip);
    #else
            StackFrame frame = new StackFrame(framesToSkip, false);
    #endif
            var method = frame.GetMethod();
            declaringType = method.DeclaringType;
            if (declaringType == null)
            {
                loggerName = method.Name;
                break;
            }
            framesToSkip++;
            loggerName = declaringType.FullName;
        } while (declaringType.Module.Name.Equals("mscorlib.dll", StringComparison.OrdinalIgnoreCase));
        return globalFactory.GetLogger(loggerName);
    }
    

    我想我会为 Log4Net 编写类似的东西作为扩展或静态方法,而不是将反射粘贴为我的锅炉代码的一部分 :)

    【讨论】:

      【解决方案3】:

      正如您所说 - 它很方便,因为您可以在不知道类名的情况下在方法中创建记录器(我知道这很简单),但允许您在类之间剪切和粘贴方法而无需重命名调用。

      【讨论】:

        【解决方案4】:

        我认为原因是,您使用.DeclaringType() 方法获取运行时类型的类型。您可以在基类中使用记录器,并且仍然可以在记录器输出中看到对象的实际类型。这使得调查更加方便。

        【讨论】:

          【解决方案5】:

          它还使得为代码生成目的创建 Codesmith 模板变得更加容易。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-01-23
            • 1970-01-01
            • 2017-02-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多