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

How to configure NLog lifestyle with Simple Injector?

我在注入记录器时遇到了生活方式问题。

NLog 期望创建实例 "Instance per Dependency",如此处所述 - https://simpleinjector.readthedocs.io/en/latest/lifetimes.html#instance-per-dependency

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

Simple Injector 告诉我我的 Transient 记录器不能注入到单例中。但是我无法将生活方式更改为 Singleton,因为那样我会丢失有关 class 正在调用记录器的上下文信息。

我的实现如下:

我编写了一个创建 NLog 实例的工厂,returns 它在实现我自己的 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());

而且我在需要日志记录的 classes 中依赖于 ILogger 接口:

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

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

其他人如何处理这个问题?有没有更好的方法?

您应该按照描述使用基于上下文的注入 here. This means that you create a generic Logger<T> implementation for (ideally your own defined) 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(...);
    }
}