2016-06-03 18 views
6

Serilog bir bağlam duyarlı kayıt cihazı oluşturmasına olanak sağlar tüketici Log.ForContext kullanılarak enjekte: Serilog en ILogger T

Log.ForContext<T>()

T olduğu böyle bir şekilde SimpleInjector ile Serilog kaydetmek istiyorum Tüketici türü, yani hangi sınıf için enjekte edilir.

örn.

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

Bu has been done with AutoFac'u görebiliyorum.

Ve SimpleInjector documentation'u inceleyerek, RegisterConditional() (Func<TypeFactoryContext, Type> parametresiyle) çok fazla gelecek vaat ediyor.

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

ancak, inşa etmek hangi Tip SimpleInjector anlatmak istemiyorum, ama nasıl birini inşa etmek.

+2

"RegisterConditional" yöntemiyle bir temsilci kaydettirin; çünkü bu, nesne grafiği oluşturma sırasında çalışma zamanı kararları vermenize izin verir ve Basit Enjektörün nesne grafikleri üzerinde derin bir analiz yapmasına izin vermez. Yani buradaki hile, "Log.ForContext " çağrısını kendi tanımlanmış bir jenerik sınıfa sarmaktır, ki bu tam olarak @janhartmann önerileridir. Serilog'u kendi soyutlamanızın ardında saklayıp saklamayacağınız size kalmış, ancak bunu kesinlikle tavsiye ediyorum. Benim için Jan'ın cevabı * doğru cevap. – Steven

+2

Ayrıca, çok fazla oturum açmadığınızdan emin olun: https://stackoverflow.com/a/9915056/264697 – Steven

cevap

7

Ben StackOverflow'daki @Steven deha Yanıta göre aşağıdaki kodla Basit Enjektör ile Serilog entegre etmiş: En Kompozisyon Root olarak 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); 
    } 

} 

: Biz açıkça olasılığını ortaya sola

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

Serilog.ILogger'ın uygulamaları thread-safe değil midir? Mümkünse koşullu kaydı 'Singleton 'yapmayı öneririm. – Steven

+2

Kesinlikle haklısınız, @Steven - inanılmaz bir hata. Cevabı şimdi düzenle. – janhartmann

+0

@janhartmann c.Consumer'ın boş olabileceği (Service Locator anti-pattern'i kullanarak inanıyorum) ve satırımı şöyle değiştirdiğini keşfettim: c => typeof (SerilogLogger <>). MakeGenericType (c.Consumer? .ImplementationType ?? typeof (object)). Ne düşünüyorsun? – jameskind