2015-09-01 28 views
6

Questa domanda è correlata alla risposta di Steven - here. Ha proposto un ottimo wrapper per il logger. Io incollare il suo codice qui sotto:Implementazione e utilizzo del wrapper logger per log4net

public interface ILogger 
{ 
    void Log(LogEntry entry); 
} 

public static class LoggerExtensions 
{ 
    public static void Log(this ILogger logger, string message) 
    { 
     logger.Log(new LogEntry(LoggingEventType.Information, 
      message, null)); 
    } 

    public static void Log(this ILogger logger, Exception exception) 
    { 
     logger.Log(new LogEntry(LoggingEventType.Error, 
      exception.Message, exception)); 
    } 

    // More methods here. 
} 

Quindi, la mia domanda è qual è il modo corretto per creare implementazione che proxy per log4net? Dovrei semplicemente aggiungere un altro metodo di estensione Log con il parametro type e quindi creare un interruttore all'interno? Utilizzare un metodo log4net diverso in caso di LoggingEventType?

E seconda domanda, qual è il modo migliore per utilizzarlo più avanti nel codice?

perché ha scritto:

(...) è possibile creare facilmente un'implementazione ILogger (...) e configurare vostro contenitore DI iniettare in classi che hanno un ILogger nella loro costruttore .

Significa che ogni classe che registrerà sth (quindi praticamente ogni), dovrebbe avere ILogger nel suo costruttore?

+1

"Questo significa che ogni classe che registrerà esimo (in modo praticamente ogni)" . Se ogni classe utilizza un programma di registrazione, si sta seriamente [registrando troppo] (https://stackoverflow.com/questions/9892137/windsor-pulling-transient-objects-from-the-taintainer). – Steven

+0

@Steven contrariamente agli upvotes e ai commenti su quella risposta, non sono assolutamente d'accordo: non si può mai registrare troppo. Soprattutto con i servizi Web e i servizi Windows (ad esempio i backend), in cui non vi sono segnalazioni di errori a un utente che si trovano di fronte a un'interfaccia utente, la registrazione è inestimabile per la risoluzione dei problemi. Certo, puoi dire "Questo codice è SOLIDO", ma se quel codice non può essere "post mortem debug" semplicemente leggendo il log per analizzare cosa stava facendo l'applicazione quando si è bloccato, allora cosa ti porta SOLID?Certo, ci sono test unitari per prevenire problemi, ma il codice non è mai perfetto. – CodeCaster

+1

@CodeCaster: ho paura di aver frainteso la mia risposta. Non sto dicendo che non dovresti loggarti. Quello che sto dicendo è che dovresti avere meno linee di codice nella tua applicazione che riguardano la registrazione. E probabilmente dovresti gettare le eccezioni più spesso. – Steven

risposta

11

Quindi, la mia domanda è qual è il modo corretto per creare l'implementazione che proxy a log4net?

si dovrebbe creare qualcosa di simile:

public class Log4netAdapter : ILogger 
{ 
    private readonly log4net.ILog m_Adaptee; 

    public Log4netAdapter(log4net.ILog adaptee) 
    { 
     m_Adaptee = adaptee; 
    } 

    public void Log(LogEntry entry) 
    { 
     //Here invoke m_Adaptee 
     if(entry.Severity == LoggingEventType.Debug) 
      m_Adaptee.Debug(entry.Message, entry.Exception); 
     else if(entry.Severity == LoggingEventType.Information) 
      m_Adaptee.Info(entry.Message, entry.Exception); 
     else if(entry.Severity == LoggingEventType.Warning) 
      m_Adaptee.Warn(entry.Message, entry.Exception); 
     else if(entry.Severity == LoggingEventType.Error) 
      m_Adaptee.Error(entry.Message, entry.Exception); 
     else 
      m_Adaptee.Fatal(entry.Message, entry.Exception); 
    } 
} 

Questo vuol dire che ogni classe che registrerà esimo (in modo praticamente ogni), dovrebbe avere ILogger nel suo costruttore?

Come ho capito dalla risposta di Stevens: Sì, dovresti farlo.

qual è il modo migliore per utilizzarlo più avanti nel codice?

Se si utilizza un contenitore DI, poi basta usare il contenitore per mappare DI ILogger-Log4netAdapter. È inoltre necessario registrare log4net.ILog o semplicemente fornire un'istanza del logger log4net al contenitore DI per iniettarlo nel costruttore Log4netAdapter.

Se non si utilizza un contenitore DI, vale a dire, si utilizza Pure DI, poi si fa qualcosa di simile:

ILog log = log4net.LogManager.GetLogger("MyClass"); 

ILogger logging_adapter = new Log4netAdapter(log); 

var myobject = new MyClass(other_dependencies_here, logging_adapter); 
+0

Non ho molto da aggiungere qui (+1 per me), tranne che come ho detto nel commento che se tu si sta iniettando 'ILogger' in quasi tutti i componenti del sistema in cui si sta effettuando la registrazione o si sta violando i principi SOLID (https://stackoverflow.com/questions/9892137/windsor-pulling-transient-objects-from- Il container). – Steven

+0

@Steven Quindi questo in pratica significa che in ogni classe quando si verifica un errore (o qualche situazione indesiderata) ho bisogno di lanciare "nuova eccezione di MyException" o di ripensare che si è verificato con "throw". Si tratta di errori/eccezioni. E riguardo la registrazione delle informazioni? Come nel server di messaggistica, voglio registrare ogni id del messaggio che sta arrivando. Devo aggiungere un altro parametro con il logger a quella classe. In realtà ogni classe che deve registrare "Info" o "Avvertenza" e non "Errore" deve avere il logger nel suo costruttore (se non è ereditato). Sei d'accordo con quest'ultima affermazione? –

+0

@TimLaax dovresti leggere di nuovo questa risposta di riferimento. Ciò che la risposta dice è che con il set di astrazioni giusto, è possibile creare un singolo decoratore che può essere avvolto attorno a un ampio set di classi, che consente di implementare la registrazione per il debug, il monitoraggio e il controllo finale in modo uniforme e in un poche righe di codice. Questo ti impedisce di dover iniettare il logger ovunque.In caso di errori, devono essere generate eccezioni. Questi possono essere registrati nel livello più alto della tua applicazione. – Steven