WPF+ Prism+ NLog

前言

我在WPF + Prism中使用NLog,但是我想在每个模块(类)中使用Microsoft.Extensions.Logging.ILogger,该如何实现。

背景

我开始制作一个示例程序,因为我希望能够使用WPF + Prism制作一个应用程序。
因为Prism官方已经将Prism.Logging从Prism框架中删除,目前选择的日志框架是NLog,通过使用Microsoft.Extensions.Logging.ILogger可以实现。虽然这可能还不是最好的用法,但是在大多数情况下,只要您知道日志级别(INFO / DEBUG / ERROR)就足够了。

对于要使用日志输出的函数,我将ILogger传递给该类的构造函数,并让Prism解决该问题。这就是它的用法。

//指定ILogger构造函数的参数,它获得注入Prism
public MainWindowViewModel(ILogger logger)
{
    logger.LogInformation("DI logger in MainWindowViewModel.cs");
}

当然,您需要为Prism的DI容器注册ILogger的实现类。使用logger,您只需要一个实现类的实例,因此

containerRegistry.RegisterInstance<Microsoft.Extensions.Logging.ILogger>(logger);

您作为参数传递的记录器,必须从Microsoft.Extensions.Logging.ILogger继承。...哦,您如何从NLog制作Microsoft.Extensionis.Logging.ILogger?

在NLog Getting Started中,

  • .NET Framework→直接使用NLog而不使用DI的示例
  • .ASP.NET Core→WebHost的UseNLog()示例
  • .NET Core控制台→Microsoft的DI容器(ServiceCollection)的AddNLog()示例

已列出。在ASP.NET Core示例中,未明确提及DI容器名称,但应使用ServiceCollection。无论如何,使用Prism的DI容器很难知道该怎么做。

因为UseNLog()和AddNLog()是NLog→(Microsoft)ILogger,所以我认为应该有这样的功能,当我再次查看.NET Core控制台示例时using NLog.Extensions.Logging; ,我注意到它已经完成了。似乎有一个函数可以执行NLog→(Microsoft)ILogger。

如果您要求不高,您会发现可以使用如下代码:不敢理解从NLog到(Microsoft)ILogger的转换using NLog.Extensions.Logging;
*使用NuGet获取NLog.Extensions.Logging
*创建NLog.config并将其复制到输出目录:如果新,请不要忘记复制它!

App.xaml.cs
using LoggerSample.Views;
using Prism.Ioc;
using Prism.Modularity;
using System.Windows;
using Microsoft.Extensions.Logging;

namespace LoggerSample
{
    public partial class App
    {
        //略

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
#if false
            // NLog.configの設定からプログラムコードで変更
            var config = new NLog.Config.LoggingConfiguration();
            var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "log/file.txt" };
            config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, logfile);
            NLog.LogManager.Configuration = config;
#endif

            var factory = new NLog.Extensions.Logging.NLogLoggerFactory();
            Microsoft.Extensions.Logging.ILogger logger = factory.CreateLogger("");

            containerRegistry.RegisterInstance<Microsoft.Extensions.Logging.ILogger>(logger);

            // DIコンテナから取り出せるよね?
            var log = Container.Resolve<Microsoft.Extensions.Logging.ILogger>();
            log.LogInformation("Test in RegsiterTypes()");
        }
    }
}
App.xaml.cs
using LoggerSample.Views;
using Prism.Ioc;
using Prism.Modularity;
using System.Windows;
using Microsoft.Extensions.Logging;

namespace LoggerSample
{
    public partial class App
    {
        //略

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
#if false
            //从该组NLog.Config的程序代码中的变化
            var config = new NLog.Config.LoggingConfiguration();
            var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "log/file.txt" };
            config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, logfile);
            NLog.LogManager.Configuration = config;
#endif

            var factory = new NLog.Extensions.Logging.NLogLoggerFactory();
            Microsoft.Extensions.Logging.ILogger logger = factory.CreateLogger("");

            containerRegistry.RegisterInstance<Microsoft.Extensions.Logging.ILogger>(logger);

            // 从集合Container中获取ILogger对象
            var log = Container.Resolve<Microsoft.Extensions.Logging.ILogger>();
            log.LogInformation("Test in RegsiterTypes()");
        }
    }
}

看起来就2020-08-06 05:34:00.5122|INFO||Test in RegsiterTypes()这么简单,我不知道日志输出的位置(模块名称)。

var logger = LogManager.GetCurrentClassLogger();是因为上面的代码并未说明它是NLog的可靠用法。可以通过将$ {callsite}放在NLogConfig的布局中来解决。就我而言,${callsite:includeNamespace=false}就足够了。

NLog.config

首先添加negut包Nlog.Config:将一下配置替换Nlog.Config内容

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off"
      internalLogFile="c:\nlog\nlog-internal.log">

  <variable name="varDataFolderPath" value="${basedir}/logs"/>
  <variable name="varLayHeader" value="${longdate}|${level}"/>
  <variable name="varLayMiddle" value="${callsite-linenumber}|${callsite:includeSourcePath=false:methodName=false}"/>
  <variable name="varLayBack" value="${message}|${exception:format=toString}"/>
  <targets>
    <target name="logFile"
            xsi:type="File"
            encoding="utf-8"
            maxArchiveFiles="100"
            archiveEvery="Day"
            archiveNumbering="Date"
            archiveDateFormat="yyyyMMdd"
            archiveFileName="${varDataFolderPath}/archives/log.{#}.txt"
            fileName="${varDataFolderPath}/nlog.txt"
            layout="${varLayHeader}|${varLayMiddle}|${varLayBack}" />
    <target xsi:type="Console"
            name="logConsole"
            layout="${varLayHeader}|${varLayMiddle}|${varLayBack}" />
  </targets>
  <rules>
    <logger minlevel="Trace" name="*" writeTo="logFile" />
    <logger minlevel="Trace" name="*" writeTo="logConsole" />
  </rules>
</nlog>

参考链接

Nlog.Config:日志方法步骤

上一篇:Prism Sample 15-FilteringEvents


下一篇:Prism Sample 16-RegionContext