Serilog 的 ILogger 使用 Log.ForContext<T> 注入,其中 T 是消费者

Serilog's ILogger injected using Log.ForContext<T>, where T is the consumer

Serilog 允许创建上下文感知记录器:

Log.ForContext<T>()

我想用 SimpleInjector 注册 Serilog,这样 T 就是消费者的类型,即它是 class 被注入的。

例如

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

我能看到这个has been done with AutoFac

并且查看 SimpleInjector documentation,有一个非常有前途的 RegisterConditional() 重载(使用 Func<TypeFactoryContext, Type> 参数)。

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

但是,我不想告诉 SimpleInjector 要构建哪个 类型,而是 如何 构建一个。

我已经将 Serilog 与 Simple Injector 集成在一起,使用以下代码基于 Whosebug 上的 @Steven genius 回答: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);
    }

}

在你的 Composition Root 中:

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