如何使用 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(...);
}
}
我在注入记录器时遇到了生活方式问题。
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
:
public class Logger<T> : ILogger
{
private readonly NLogLogger logger = new NLogLogger(typeof(T));
public void Log(LogEntry entry)
{
logger.Log(...);
}
}