6

Gibt es eine Möglichkeit, den Kontext abrufen, so dass ich die loggerName abrufen und LogManager.GetLogger(loggerName) anstelle von LogManager.GetCurrentClassLogger() verwenden kann?Registrieren NLog ILogger mit einfachem Injektor

Ich bemerkte, container.RegisterConditional() hat Zugriff auf den Kontext.

Auch ich möchte Lösungen wie SimpleLogging.NLog für jetzt vermeiden.

Schließlich bin ich bereit zu akzeptieren, dass dies nicht der richtige Ansatz ist. BTW, AOP ist eine Option, die ich bereits erkundet habe (Is it a good practice to have logger as a singleton?).

Hinweis: Mir ist bekannt, dass GetCurrentClassLogger() die gleichen Informationen erhält, die ich mit .NET Reflection abrufen würde.

+0

was möchten Sie den Wert von 'LoggerName' zu ​​sein? – qujck

+1

Related: https://Stackoverflow.com/q/32952701/264697 – Steven

+1

Anwendung von AOP-Techniken ist sehr nützlich, aber bitte bleiben Sie weg von Code Web-Tools. Wenden Sie AOP an, indem Sie Dekoratoren verwenden. Related: https://Stackoverflow.com/a/9915056/264697 – Steven

Antwort

7

Sie müssen einen Proxy-Logger definieren, der die Nachricht an den richtigen Log Logger weiterleitet. Dieser Proxy ist ziemlich einfach:

public class NLogProxy<T> : ILogger 
{ 
    private static readonly NLog.ILogger logger = 
       LogManager.GetLogger(typeof (T).FullName); 

    void ILogger.Log(string message) 
    { 
     logger.Log(LogLevel.Info, message); 
    } 
} 

Sie dies als registrieren

container.RegisterConditional(typeof(ILogger), 
    context => typeof(NLogProxy<>).MakeGenericType(context.Consumer.ImplementationType), 
    Lifestyle.Singleton, context => true); 

Überall, wo Sie brauchen Anmeldung erhalten Sie nur ILogger injizieren.

Wie für AOP. Ich bin nicht sicher, was Sie mit diesem Kommentar meinen

Ein Wrapper, der gepflegt werden muss (NLog.ILogger Vertrag ist riesig).

Logging ist ein cross cutting concern und decorator ist eine großartige Art und Weise Querschnittsthemen anzuwenden. Mit einem Dekorator wird es nicht möglich sein, jeden (privaten) Funktionsaufruf zu protokollieren, Eingang und Ausgang, aber warum möchten Sie das? Wie Sie here lesen können, brauchen Sie das wahrscheinlich nicht. Die einfache Tatsache, dass ein Service aufgerufen wird (mit den an diesen Service übergebenen Daten) und mögliche Ausnahmen werden mit dem kompletten Stacktrace protokolliert, ist in den meisten Fällen mehr als ausreichend.

public interface ISomeService 
{ 
    void DoSomething(string someParameter); 
} 

public class SomeServiceDecorator : ISomeService 
{ 
    private readonly ISomeService decoratee; 
    private readonly ILogger logger; 

    public SomeServiceDecorator(ISomeService decoratee, ILogger logger) 
    { 
     this.decoratee = decoratee; 
     this.logger = logger; 
    } 

    public void DoSomething(string someParameter) 
    { 
     try 
     { 
      this.logger.Log(string.Format("Do something called with {0}", someParameter)); 
      this.decoratee.DoSomething(someParameter); 
     } 
     catch (Exception e) 
     { 
      this.logger.Log(e.ToString());     
      throw; 
     } 
    } 
} 

Dieser Dekorateur loggt alle Funktion mit dem an den Dienst weitergegeben Informationen aufruft und protokolliert auch jede Ausnahme:

dies so betrachten.

Aber dieser Ansatz würde die Anzahl der Klassen um 2 erhöhen, also nicht sehr DRY. Dieses Problem wird verursacht, weil dieses Design mindestens suboptimal ist. Die Verwendung eines Entwurfs um eine einzelne offene generische Abstraktion wird dieses Problem vollständig lösen. Sie können über dieses Design here und here lesen.

In diesem Fall würden Sie einen einzigen `LoggingDecorator‘ haben als

public class LoggingCommandHandlerDecorator<T> : ICommandHandler<T> 
{ 
    private readonly ICommandHandler<T> decoratee; 
    private readonly ILogger logger; 

    public LoggingCommandHandlerDecorator(ICommandHandler<T> decoratee, ILogger logger) 
    { 
     this.decoratee = decoratee; 
     this.logger = logger; 
    } 

    public void Handle(T command) 
    { 
     // serialize command to json and log 
     this.logger.Log(serializedcommandData); 
     this.decoratee.Handle(command); 
    } 
} 

Und dieses einzelne Dekorateur werden alle Ihre Befehle protokolliert.

Das ist meine Vision von AOP ....

+1

@ ric-net Ich denke Ihre Antwort adressiert nicht nur Steven Kommentare, sondern hebt auch Jeff Atwoods Protokollierung hervor: [Das Problem mit der Protokollierung] (http://blog.codinghorror.com/the-problem-with-logging/). Eine interessante alte, aber gute Diskussion, mit der sich jeder Architekt auseinandersetzen muss. –

+0

Wirklich hilfreich, danke – james