2011-07-18 5 views
3

J'ai une classe générique:Comment utiliser le nom de classe complet comme nom de journal avec NLog?

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

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

Utilisé avec une configuration simple 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> 

Je voudrais que ma sortie de journal pour ressembler à quelque chose comme:

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

Au lieu de cela, ce Je vois est:

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

Comment puis-je demander au consignateur d'utiliser le nom de type complet au lieu du nom de base qui affiche uniquement le nombre de paramètres génériques?

Répondre

3

Au lieu de GetCurrentClassLogger, vous pouvez utiliser:

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))) 
      + ">"; 
} 

Lieu GenericToString où vous gardez les fonctions/méthodes d'extension utilité aléatoire. Clause de non-responsabilité: la fonction a été piratée en ce moment et pourrait ne pas fonctionner, faire prendre feu à votre ordinateur ou provoquer la calvitie.

+0

Oui je pouvais faire bien sûr, cela, mais je ne voulais pas avoir à rememb er appeler cette méthode à chaque fois (et avoir la dépendance supplémentaire sur l'assemblage des utilitaires communs). Une meilleure approche serait si NLog l'a fait car je pense que la sortie actuelle n'est pas très utile. Je me rends compte qu'il peut y avoir un coup de touche dans le petit peu de réflexion supplémentaire nécessaire, mais ce serait bien d'avoir au moins l'option pour l'allumer – emertechie

+0

@Andrew: bien que cela soit bien intégré, c'est quelque chose que vous aurez demander aux développeurs NLog de le faire. Entre-temps, vous pouvez répliquer le sniffing stacktrace (ou le copier-coller depuis leur source) et créer une méthode d'extension sur LogManager. – millimoose

+0

@AndrewSmith probablement vous pouvez écrire une méthode d'extension prenant des génériques, et aussi l'appeler GetLogger. A l'intérieur, vous utilisez la méthode d'Inerdial pour créer le nom. à sa manière, vous ne devez pas vous souvenir de quoi que ce soit:] – stijn

1

Si vous utilisez C# 6 & .NET> 4.5, vous pouvez faire une astuce pour utiliser 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); 
     } 
    } 
} 

Ensuite, vous pouvez utiliser cette extension comme ceci:

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

sortie sera:

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