注射记录器时,我正在努力解决生活方式问题。
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所期望的那样?
其他人如何处理此问题?还有更好的方法吗?
答案 0 :(得分:5)
您应该按照here所述使用基于上下文的注入。这意味着您为(理想情况下为your own defined)Logger<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(...);
}
}