使用 NLog 进行依赖注入

问题描述 投票:0回答:3

我有一个 .NET Core Web 应用程序,我正在尝试通过 NLog 添加日志记录。 在之前的项目中,我只是在每个类的顶部使用了类似以下内容:

private static Logger logger = LogManager.GetCurrentClassLogger();

我正在尝试尽可能在这个项目中遵循更多最佳实践。

我的问题是,如何注入一个具有要注入的类的完全限定名称的记录器?

在我的startup.cs文件中,到目前为止我有以下内容:

services.AddScoped<BLL.Logging.NLogLogger>();

目前,

NLogLogger
类通过
GetCurrentClassLogger()
创建NLog Logger的实例,使用时只会将名称报告为“BLL.Logging.NLogLogger”,而不是记录器被注入的实际类进入。

简化问题并使其更通用: 如何传入 .NET Core 将要注入类的类的名称?

我考虑过类似下面的事情,但不知道如何实现它:

services.AddScoped<BLL.Logging.NLogLogger>(serviceProvider => new BLL.Logging.NLogLogger("class name here"));
logging dependency-injection asp.net-core nlog
3个回答
18
投票

使用 DI 指定

ILogger<T>
类型而不是
Logger
,其中
T
是使用记录器的类类型,因此 NLog 将了解该类。例如:

public class TodoController : Controller
{
    private readonly ILogger _logger;

    public TodoController(ILogger<TodoController> logger)
    {
        _logger = logger;
    }
}

参考资料:


9
投票

我想我已经找到了一个可以接受的解决方案,尽管不完全是我问问题的方式。

首先,我创建一个“LoggerFactory”,它有一个名为“GetLogger”的方法(它创建具体的 NLog Logger 并接受类名作为参数),然后我注入这个工厂而不是直接注入记录器。

记录器工厂:

public class LoggerFactory : ILoggerFactory
{
    public ILogger GetLogger(string fullyQualifiedClassName)
    {
        return new NLogLogger(fullyQualifiedClassName);
    }
}

NLogLogger:

public class NLogLogger : ILogger, INLogLogger
{
    NLog.Logger mylogger;
    public NLogLogger(string fullyQualifiedClassName)
    {
        mylogger = NLog.LogManager.GetLogger(fullyQualifiedClassName);
    }
}

Startup.cs:

services.AddScoped<BLL.Logging.ILoggerFactory>();

在我的控制器类中,我有:

    private BLL.Logging.ILogger logger;//my NLogLogger inherits this interface

    public HomeController(BLL.Logging.ILoggerFactory loggerFactory)
    {
        logger = loggerFactory.GetLogger(this.GetType().FullName);
    }

所以我现在有效地所做的,不是注入实际的 Logger 本身(@Steven 表示这不可能按照我尝试的方式实现),而是注入实用程序来创建一个实例包装 NLog 的记录器。

我仍然有责任在类中创建记录器,但至少我已经与底层日志框架(NLog)解耦。


0
投票

如果您不想在控制器中依赖 NLog(因此您需要依赖 Microsoft 抽象):

在您的命令处理程序/控制器中

class MyHandler(ILoggerFactory loggerFactory)
{
    public void Handler()
    {
        var logger = loggerFactory.GetLogger("myCustomLogger");
        logger?.LogDebug("My log");
    }
}

ILoggerFactory

using Microsoft.Extensions.Logging;
public interface ILoggerFactory
{
    ILogger GetLogger(string name);
}

LoggerFactory

using NLog.Extensions.Logging;
public class LoggerFactory : ILoggerFactory
{
    private readonly NLogLoggerProvider _nLogLoggerProvider = new();

    public Microsoft.Extensions.Logging.ILogger GetLogger(string name)
    {
        return _nLogLoggerProvider.CreateLogger(name);
    }
}

依赖注入

 using var servicesProvider = new ServiceCollection()
     .AddSingleton<ILoggerFactory, LoggerFactory>()
     .BuildServiceProvider();

nlog.config

<rules>
  <logger name="myCustomLogger" minlevel="Trace" writeTo="myCustomFile" final="true" /> <!-- final so that myCustomLogger only logs in this rule -->
  <logger name="*" minlevel="Trace" writeTo="logfile" />
</rules>


<targets>
  <target xsi:type="File" name="logfile" fileName="C:\MyApp\logs\log.log"
          layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
  
  <target xsi:type="File" name="myCustomFile" fileName="C:\MyApp\logs\lastHttpCall.log"
          layout="${message}" replaceFileContentsOnEachWrite="true" />
</targets>
© www.soinside.com 2019 - 2024. All rights reserved.