【问题标题】:How to use fully qualified class name as logger name with NLog?如何使用完全限定的类名作为 NLog 的记录器名称?
【发布时间】:2016-09-23 19:55:00
【问题描述】:

我有一个通用类:

public class GenericClass<A>
{
    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

    public void Blah(A a)
    {
        Logger.Info("Test log");
    }
}

与简单的 NLog 配置一起使用:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <targets>
    <target name="console" xsi:type="ColoredConsole" />
  </targets>

  <rules>
    <logger name="*" minlevel="Trace" writeTo="console" />
  </rules>
</nlog>

我希望我的日志输出看起来像:

...|INFO|NLogTests.GenericClass<System.String>|Test log

相反,我看到的是:

...|INFO|NLogTests.GenericClass`1|Test log

如何让 logger 使用完全限定的类型名称而不是只显示泛型参数数量的基本名称?

【问题讨论】:

    标签: nlog


    【解决方案1】:

    您可以使用 GetCurrentClassLogger,而不是:

    Logger log = LogManager.GetLogger(GenericToString(typeof(GenericClass<A>)));
    …
    string GenericToString(Type type) {
      var typeName = type.Namespace + "." + type.Name;
      var args = type.GetGenericArguments();
      if (args.Count() == 0) return typeName;
    
      typeName = typeName.Remove(typeName.LastIndexOf("`"));
      return typeName 
               + "<" 
               + string.Join(", ", args.Select(a=>GenericToString(a)))
               + ">";
    }
    

    GenericToString 放置在您保存随机实用程序函数/扩展方法的任何位置。

    免责声明:该功能现在被黑了,可能无法工作,使您的计算机着火,或导致秃顶。

    【讨论】:

    • 是的,我当然可以这样做,但我不想每次都记得调用该方法(并且对常用的 utils 程序集有额外的依赖)。更好的方法是如果 NLog 这样做,因为我认为当前输出不是很有用。我意识到可能需要一点额外的反射,但至少可以选择打开它会很好
    • @Andrew:虽然内置这个功能可能很好,但您必须要求 NLog 开发人员这样做。在此期间,您可以复制堆栈跟踪嗅探(或从其源复制粘贴)并在 LogManager 上创建扩展方法。
    • @AndrewSmith 可能您可以编写一个采用泛型的扩展方法,也可以将其称为 GetLogger。在里面你使用 Inerdial 的方法来创建名称。他的方式你不必记住任何东西:]
    【解决方案2】:

    如果您使用的是 C# 6 和 .NET > 4.5,那么您可以巧妙地使用CSharpCodeProvider

    public static class LogManager<T>
    {
        public static Logger GetLogger()
        {
            return LogManager.GetLogger(typeof(T).GetFriendlyName());
        }
    }
    
    public static class TypeExtensions
    {
        public static string GetFriendlyName(this Type t)
        {
            using (var provider = new CSharpCodeProvider())
            {
                var typeRef = new CodeTypeReference(t);
                return provider.GetTypeOutput(typeRef);
            }
        }
    }
    

    然后你可以像这样使用这个扩展:

    var logger = LogManager<Dictionary<string, int>>.GetLogger();
    logger.Info("logger name contains generic params");
    

    输出将是:

    2016-09-23 13:52:14.6342|INFO|System.Collections.Generic.Dictionary<string, int>|logger name contains generic params
    

    【讨论】:

      猜你喜欢
      • 2012-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-27
      • 2021-12-21
      • 2020-11-12
      • 1970-01-01
      相关资源
      最近更新 更多