如何使用简单注射器配置 NLog 生活方式?



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

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

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

简单注入器告诉我,我的瞬态记录器无法注入单例。但是我无法将生活方式更改为 Singleton,因为这样我就会丢失有关哪个类正在调用记录器的上下文信息。

我的实现如下:

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

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

我用简单注射器注册了这个,因此:

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;
}
}

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

其他人是如何处理的?有没有更好的方法?

应使用基于上下文的注入,如此处所述。这意味着您为(理想情况下是你自己定义的)ILogger创建一个通用Logger<T>实现,并使用使用者的上下文注册它:

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(...);
}
}

最新更新