2009-02-06 18 views
26

Mi chiedevo quali erano le migliori pratiche in merito ai registri di registrazione e registrazione e all'iniezione delle dipendenze. Specificamente, se sto progettando una classe che ha bisogno di un modo per accedere, come dovrei fare per ottenere un'interfaccia da registrare per tenere a mente l'iniezione di dipendenza?interfacce di registrazione e registrazione delle dipendenze

Iniezione di dipendenza sembra indicare che le dipendenze esterne devono essere iniettate dall'esterno (costruttore o setter di proprietà), quindi dovrei prendere un'istanza ILog nel costruttore e usarla nella classe? Dovrei considerare di loggare una dipendenza opzionale e metterla in un setter? Sto spingendo per troppa flessibilità consentendo la modifica dell'interfaccia di logging e dovrei semplicemente prendere una dura dipendenza da un'interfaccia di registrazione specifica (ad esempio, creare una variabile ILog statica tramite una chiamata a un metodo factory)? Questo richiamo del metodo factory può essere richiamato nel contenitore per ottenere l'implementazione di ILog o creerà conflitti di inizializzazione tra le variabili statiche in fase di inizializzazione e il contenitore IoC inizializzato?

dovrei fare questo:

public class MyService : ISomeService 
{ 
    private static readonly ILogger s_log = 
      LoggingFactory.GetLogger(typeof(MyService)) 
    ... 
} 

o forse questo:

public class MyService : ISomeService 
{ 
    protected virtual ILogger Logger {get; private set;} 
    public MyService(ILogger logger, [other dependencies]) 
    { 
    Logger = logger; 
    } 
} 

o anche questo:

public class MyService : ISomeService 
{ 
    public virtual ILogger Logger {get; set;} 
    public MyService() 
    { 
    } 
} 

Altri modelli o modi per fare questo? Cosa stanno facendo le persone là fuori? Cosa funziona e quando?

+0

Vorrei optare per la seconda o terza opzione a seconda se avere o meno un logger per il servizio è considerato critico. – toad

risposta

4

È fantastico che si stia esaminando l'inversione di controllo e l'iniezione di dipendenza.

Ma per la tua domanda, c'è un altro concetto che potresti voler esaminare: la programmazione orientata agli aspetti.

In .NET, sono disponibili alcuni validi framework per la programmazione orientata agli aspetti, tra cui Castle, LinFu e il blocco di applicazione di policy in Microsoft. In effetti, alcuni contenitori di inversione di controllo hanno anche alcune caratteristiche orientate all'aspetto.

Questi concetti e strumenti aiutano a rendere problematiche come la registrazione come sede di background in termini di rumore del codice e devono essere gestiti automaticamente.

+1

La registrazione è il "buongiorno" della programmazione orientata agli aspetti. È sicuramente una preoccupazione trasversale. – duffymo

+6

La gestione della traccia del metodo e delle eccezioni è una cosa, ma per quanto riguarda la registrazione degli eventi positiva? Che dire delle condizioni di avviso che devi registrare quando accadono, ma non interrompere il flusso del programma. Puoi riguardare casi "tutti (rilevanti)" con aspetti? – Cornelius

2

Questa non sarà una risposta completa, ma una considerazione sarà che se si inietta il ILog tramite il costruttore della classe, è possibile quindi prendere in giro il framework di registrazione per il test dell'unità. Altri pensieri ... Un setter di proprietà per il passaggio nel ILog significa che non è possibile registrare azioni dal costruttore. Inoltre, non sai per certo se la tua istanza abbia anche un ILog disponibile, il che significa che devi completare ogni chiamata con un test per un'istanza ILog valida.

+0

+1 per suggerimenti sui test dell'unità + oggetti finti. –

0

Mi limiterei a iniettarlo e utilizzare un'interfaccia. Principalmente per facilitare i test. Rendere è più facile sostituire un mock o uno stub durante il test dell'oggetto consumante.

Vorrei basare se ho utilizzato la funzione di costruzione o setter di iniezione sull'importanza del registro per la classe di consumo. Se si desidera che sia critico, preferirei l'iniezione del costruttore, se facoltativo, quindi setter.

Non vedo dove utilizzare un metodo factory non possa funzionare con il container, tuttavia, rende quindi il test della classe consumer dipendente da una corretta configurazione di questo metodo factory.

4

Il mio consiglio? Avvolgi le interfacce di registrazione nel tuo.Ho preso una dipendenza su Log4Net una volta, mi sono bruciato e ho dovuto refactoring molti dei miei progetti a causa di esso.

+0

http://stackoverflow.com/questions/940831/how-to-use-log4net-with-dependency-injection – Karsten

+0

@Karsten anche se si inserisce il logger è necessario aggiungere un riferimento a ogni progetto che lo utilizzerà che la classe o l'interfaccia possono essere risolti. La soluzione dell'utilizzo di una callback isola il 100% dell'implementazione nello scope in cui viene creata la classe. – QueueHammer