【问题标题】:How to configure NLog lifestyle with Simple Injector?如何使用 Simple Injector 配置 NLog 生活方式?
【发布时间】:2017-08-16 05:10:40
【问题描述】:

在注入记录器时,我正在努力解决生活方式问题。

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 所期望的?

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

【问题讨论】:

  • 'NLog 期望实例被创建为“每个依赖的实例”'。你在哪里读到的?据我所知,您的记录器可以是单身人士。
  • 我的陈述可能有点生硬——我相信它可以用任何一种方式。但我想使用“LogManager.GetCurrentClassLogger()”,它会自动获取调用类和方法的名称。如果记录器是单例,则无法使用此功能。 (这可能是一个有效的妥协,取决于你的需要......)
  • Logger&lt;T&gt; 解决了这个问题。

标签: logging dependency-injection nlog simple-injector


【解决方案1】:

您应该按照here 的描述使用基于上下文的注入。这意味着您为(理想情况下为your own defined)ILogger 创建一个通用的Logger&lt;T&gt; 实现,并使用消费者的上下文进行注册:

container.RegisterConditional(
    typeof(ILogger),
    c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
    Lifestyle.Singleton,
    c => true);

这样的Logger&lt;T&gt; 实现会在使用提供的T 时将调用转发到NLog:

public class Logger<T> : ILogger
{
    private readonly NLogLogger logger = new NLogLogger(typeof(T));

    public void Log(LogEntry entry)
    {
        logger.Log(...);
    }
}

【讨论】:

  • 这是个好主意。谢谢!
  • 我已经更详细地研究了这一点,但现在不太确定。 “RegisterConditional”文档说该实例是根据生活方式缓存的。这意味着我可以在内存中缓存许多记录器实例,具体取决于它们的使用位置。我说对了吗?
  • @freshr:由于Logger&lt;T&gt; 是通用的,将其注册为Singleton 意味着,每个关闭的T 将只有1 个实例。所以这也意味着每个消费者有一个 NLog 记录器。但是,如果您考虑一下,这很明显,并且应该不是问题。此外,如果您在系统中的许多类中注入ILogger,您将might be doing something wrong。
  • 我同意将这些 Logger 实例留在内存中应该不是问题,太多表示有问题。不过我并不热衷于此,所以我只是在需要测试的地方注入了一个记录器工厂。我在调查这个问题时学到了很多东西,并且从阅读你的博客中学到了很多。非常感谢。
  • 如果你注入工厂,也请回复:cuttingedge.it/blogs/steven/pivot/entry.php?id=100
猜你喜欢
  • 2018-08-29
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多