如何使用Simple Injector配置NLog生活方式?

时间:2017-03-23 14:51:30

标签: logging dependency-injection nlog simple-injector

注射记录器时,我正在努力解决生活方式问题。

NLog期望创建实例"每个依赖关系的实例",如此处所述 - https://simpleinjector.readthedocs.io/en/latest/lifetimes.html#instance-per-dependency

使用工厂方法LogManager.GetCurrentClassLogger()完成记录器创建。使用此模式允许记录器获取调用者的名称,以便将其包含在记录的消息中。

Simple Injector告诉我,我的瞬态记录器不能注入单例。但是我不能改变生活方式给Singleton,因为我会失去关于哪个类调用记录器的上下文信息。

我的实施如下:

我编写了一个创建NLog实例的工厂,并在一个实现我自己的ILogger抽象的包装器中返回它:

internal class LoggerFactory : ILoggerFactory
{
    public ILogger GetLogger()
    {
       return new NLogLogger(LogManager.GetCurrentClassLogger());
    }
}

我用Simple Injector注册了这个:

container.RegisterSingleton<ILoggerFactory, LoggerFactoryInstance>();
container.Register<ILogger>(
    () => container.GetInstance<ILoggerFactory>().GetLogger());

我依赖于需要记录的类中的ILogger接口:

public class MyClass
{
    private readonly ILogger _logger;
    public MyClass(ILogger logger)
    {
        _logger = logger;
    }
}

我必须注射工厂吗?我宁愿不必在任何地方使用它来解析记录器,但也许这就是Simple Injector所期望的那样?

其他人如何处理此问题?还有更好的方法吗?

1 个答案:

答案 0 :(得分:5)

您应该按照here所述使用基于上下文的注入。这意味着您为(理想情况下为your own definedLogger<T>创建了通用ILogger实现,并使用使用者的上下文进行注册:

container.RegisterConditional(
    typeof(ILogger),
    c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
    Lifestyle.Singleton,
    c => true);

此类Logger<T>实施会在使用提供的T时将呼叫转发给NLog:

public class Logger<T> : ILogger
{
    private readonly NLogLogger logger = new NLogLogger(typeof(T));

    public void Log(LogEntry entry)
    {
        logger.Log(...);
    }
}