fre*_*shr 2 logging dependency-injection nlog simple-injector
注入记录器时,我正在为生活方式问题而苦苦挣扎。
NLOG预期实例被创建“按相关性实例”,这里描述- https://simpleinjector.readthedocs.io/en/latest/lifetimes.html#instance-per-dependency。
使用工厂方法完成记录器的创建LogManager.GetCurrentClassLogger()。使用此模式,记录器可以获取呼叫者的姓名,以便将其包括在记录的消息中。
Simple Injector告诉我,我的Transient记录器无法注入单例。但是我无法将生活方式更改为Singleton,因为这样我会丢失有关哪个类正在调用记录器的上下文信息。
我的实现如下:
我编写了一个工厂,该工厂创建NLog实例,并在实现我自己的ILogger抽象的包装器中将其返回:
internal class LoggerFactory : ILoggerFactory
{
public ILogger GetLogger()
{
return new NLogLogger(LogManager.GetCurrentClassLogger());
}
}
Run Code Online (Sandbox Code Playgroud)
我这样在Simple Injector上注册了它:
container.RegisterSingleton<ILoggerFactory, LoggerFactoryInstance>();
container.Register<ILogger>(
() => container.GetInstance<ILoggerFactory>().GetLogger());
Run Code Online (Sandbox Code Playgroud)
而且我依赖需要记录的类中的ILogger接口:
public class MyClass
{
private readonly ILogger _logger;
public MyClass(ILogger logger)
{
_logger = logger;
}
}
Run Code Online (Sandbox Code Playgroud)
我必须注入工厂吗?我宁愿不必在要使用它的任何地方解析记录器,但是也许这就是Simple Injector所期望的?
其他人如何处理呢?有没有更好的办法?
您应该按照此处所述使用基于上下文的注入。这意味着您Logger<T>将为(最好是您自己定义的)创建通用实现,ILogger并使用使用者的上下文进行注册:
container.RegisterConditional(
typeof(ILogger),
c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
Run Code Online (Sandbox Code Playgroud)
这样的Logger<T>实现将在使用提供的代码时将调用转发给NLog T:
public class Logger<T> : ILogger
{
private readonly NLogLogger logger = new NLogLogger(typeof(T));
public void Log(LogEntry entry)
{
logger.Log(...);
}
}
Run Code Online (Sandbox Code Playgroud)