2012-12-04 8 views
8

Alla ricerca di a project che utilizza Common.Logging per .NET, ho notato che alcune classi dichiarano l'istanza del logger come membro statico di classe. Per esempio:In C# il mio logger Common.Logging può essere un membro di istanza o statico?

public class HelloJob : IJob 
{ 
    private static ILog _log = LogManager.GetLogger(typeof(HelloJob)); 

    public HelloJob() 
    { 
    } 

    public virtual void Execute(IJobExecutionContext context) 
    { 
     _log.Info(string.Format("Hello World! - {0}", System.DateTime.Now.ToString("r"))); 
    } 
} 

E in altre classi logger è dichiarato come un membro di istanza:

public class SimpleExample : IExample 
{ 
    public virtual void Run() 
    { 
     ILog log = LogManager.GetLogger(typeof (SimpleExample)); 

     log.Info("------- Initializing ----------------------"); 

     // etc 
    } 
}  

C'è un motivo per preferire un approccio o l'altro?

In quali casi è consigliato ogni approccio? È legato alla sicurezza del filo?

Sarebbe un problema se avessi appena dichiarato una classe "Logger" con un membro "logger" statico e l'intero progetto lo usasse (a parte il problema che avrei in pratica una variabile globale)?

risposta

9

La maggior parte dei logger sono thread-safe, e la creazione di istanze di essi ha un sovraccarico molto piccolo, sia in termini di tempo che di memoria. Quindi la vera domanda deve essere quella che ha senso dal punto di vista della programmazione e della manutenzione.

Da un lato, dal momento che lo strumento sia concettualmente legato al tuo classe, e non al istanza della classe, un sacco di gente preferisce tenerlo statica. Questo è un argomento perfettamente valido. Ad esempio, seestende HelloJob, penso che la maggior parte delle persone si aspetterebbe che il messaggio di registro scritto dal codice in HelloJob si leghi alla classe HelloJob, anche se si dispone di un'istanza di sottoclasse più specifica. È anche bello poter accedere al tuo logger da metodi statici, cosa che non sarebbe possibile se non fosse su un campo statico.

D'altra parte, non vi è alcun motivo per cui HelloJob dovrebbe essere responsabile di ottenere la propria istanza di registrazione. C'è molto da dire sull'utilizzo dell'iniezione di dipendenza (testabilità dell'unità, configurabilità aggiuntiva e codice più semplice). Quindi personalmente suggerisco di far inserire il logger da un framework DI, nel qual caso bisognerà fare riferimento a un campo per istanza.

public class HelloJob : IJob 
{ 
    private readonly ILog _log; 

    public HelloJob(ILog log) 
    { 
     _log = log; 
    } 
    ... 
} 

Il vostro quadro DI può impostare il registratore in base a particolari sa in fase di esecuzione, oppure si può fornire un falso o logger deriso nel vostro unit test per assicurarsi che i messaggi di log attesi sono prodotti. Nota che anche se ti stai riferendo ad un campo per istanza, sei perfettamente libero di usare ancora un'istanza per classe (o anche un singleton) - questi sono solo dettagli che non devono necessariamente far parte di questa classe preoccupazione.

+0

'LogManager.GetLogger' è probabilmente implementato internamente tramite l'integrazione delle dipendenze; cioè, la dipendenza è gestita all'interno del logger. Non vorrei che i miei logger fossero archiviati come "campi per istanza" e ricevessi quell'overhead per ogni istanza creata. Lo memorizza staticamente una volta quando la classe viene caricata per la prima volta funziona per me. –

+2

@ChrisSinclair: È vero che i dettagli di istanziazione * sono gestiti da LogManager.GetLogger e mi piace che Commons.Logging fornisca un'interfaccia di registrazione comune, lasciandoti libero di cambiare i framework, le configurazioni, ecc. Sottostanti. Tuttavia, questo è un esempio del modello di fabbrica, non di dipendenza da iniezione. Il modello di fabbrica comporta molti vantaggi rispetto all'istanziazione manuale, ma l'iniezione di dipendenza comporta ancora ulteriori vantaggi. Il tuo framework DI può ancora essere impostato per riutilizzare un singolo logger per ciascun tipo, e il sovraccarico è praticamente incommensurabile il 90% delle volte. – StriplingWarrior

+0

Nella documentazione Common.Logging si afferma che i LogManager pubblici statici sono thread-safe, ma i metodi di istanza non lo sono, il che sembra contrario a questa risposta. http://netcommon.sourceforge.net/docs/2.0.0/api/html/Common.Logging~Common.Logging.LogManager.html – coderjoe

Problemi correlati