2016-06-03 54 views
6

Serilog permette la creazione di un contesto consapevole logger:di Serilog ILogger iniettato usando Log.ForContext <T>, dove T è il consumatore

Log.ForContext<T>()

vorrei registro Serilog con SimpleInjector in modo tale che è T il tipo di consumatore, cioè è a quale classe è iniettato.

ad es.

public class Car 
{ 
    public Car(ILogger logger) <= would be injected using Log.ForContext<Car>() 
    {    
    } 
} 

posso vedere questo has been done with AutoFac.

E guardando attraverso il SimpleInjector documentation, c'è un sovraccarico molto promettente di RegisterConditional() (con il parametro Func<TypeFactoryContext, Type>).

c.RegisterConditional(typeof (ILogger), 
    x => Log.ForContext(x.Consumer.ImplementationType), <= won't compile as expecting a Type 
    Lifestyle.Scoped, 
    x => true); 

però, non voglio dire SimpleInjector che Tipo costruire, ma come costruire uno.

+2

Abbiamo esplicitamente lasciato fuori la possibilità di registrare un delegato con il metodo 'RegisterConditional', perché ciò consentirebbe di prendere decisioni di runtime durante la creazione del grafo di oggetti, e non consente a Simple Injector di eseguire analisi approfondite sui grafici degli oggetti. Quindi questo trucco è quello di racchiudere la chiamata 'Log.ForContext ' all'interno di una classe generica definita automaticamente, che è esattamente ciò che consiglia @janhartmann. Che tu nasconda o meno Serilog dietro la tua astrazione dipende da te, ma io assolutamente consiglio di farlo. Quindi per me, la risposta di Jan è * la * risposta corretta. – Steven

+2

Assicurati anche di non registrare troppo: https://stackoverflow.com/a/9915056/264697 – Steven

risposta

7

ho integrato Serilog con semplice iniettore con il seguente codice in base a @Steven risposta genio su StackOverflow: logger wrapper best practice

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

public class SerilogLogger<T> : ILogger 
{ 
    private readonly Serilog.ILogger _logger; 

    public SerilogLogger() 
    { 
     _logger = new LoggerConfiguration() 
      .WriteTo 
      .Trace(LogEventLevel.Information) 
      .CreateLogger() 
      .ForContext(typeof (T)); 
    } 

    public void Log(LogEntry entry) 
    { 
     /* Logging abstraction handling */ 
    } 
} 

public static class ContainerExtensions { 

    public static void RegisterLogging(this Container container) 
    { 
     container.RegisterConditional(
      typeof(ILogger), 
      c => typeof(SerilogLogger<>).MakeGenericType(c.Consumer.ImplementationType), 
      Lifestyle.Singleton, 
      c => true); 
    } 

} 

nella root Composizione:

var container = new Container(); 
container.RegisterLogging(); 
+3

Le implementazioni di 'Serilog.ILogger' non sono thread-safe? Suggerirei di effettuare la registrazione condizionale 'Singleton' se possibile. – Steven

+2

Hai assolutamente ragione, @Steven - un errore in modo evidente. Modifica risposta ora. – janhartmann

+0

@janhartmann Ho scoperto che ci sono momenti in cui c.Consumer potrebbe essere nullo (credo attraverso il Service Locator anti pattern) e ho modificato la mia riga in questo modo: 'c => typeof (SerilogLogger <>). MakeGenericType (c.Consumer? .ImplementationType ?? typeof (oggetto)) '. Cosa ne pensi? – jameskind