当借助CommunityToolkit.Mvvm工具来开发WPF,
通过官方示例可见,IOC提供了很大的便利,可以将服务接口,ViewModel放到容器
public sealed partial class App : Application
{
public App()
{
Services = ConfigureServices();
this.InitializeComponent();
}
/// <summary>
/// Gets the current <see cref="App"/> instance in use
/// </summary>
public new static App Current => (App)Application.Current;
/// <summary>
/// Gets the <see cref="IServiceProvider"/> instance to resolve application services.
/// </summary>
public IServiceProvider Services { get; }
/// <summary>
/// Configures the services for the application.
/// </summary>
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
services.AddSingleton<IFilesService, FilesService>();
services.AddSingleton<ISettingsService, SettingsService>();
services.AddSingleton<IClipboardService, ClipboardService>();
services.AddSingleton<IShareService, ShareService>();
services.AddSingleton<IEmailService, EmailService>();
return services.BuildServiceProvider();
}
}
在ConfigureServices方法中,可以将本文我们将要用到的Nlog模块引入系统中,从Nlog官网去找方法:
先把依赖包引用好。。。
1:代码配置
var config = new NLog.Config.LoggingConfiguration();
// Targets where to log to: File and Console
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "file.txt" };
var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
// Rules for mapping loggers to targets
config.AddRule(LogLevel.Info, LogLevel.Fatal, logconsole);
config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
// Apply config
NLog.LogManager.Configuration = config;
NLog 5.0可以这样写:
NLog.LogManager.Setup().LoadConfiguration(builder => {
builder.ForLogger().FilterMinLevel(LogLevel.Info).WriteToConsole();
builder.ForLogger().FilterMinLevel(LogLevel.Debug).WriteToFile(fileName: "file.txt");
});
2:appsettings.json配置
前提是:你的程序是ASP.NET Core或.NET Core应用程序,并且要使用
NLog.Extensions.Logging 或 NLog.Web.AspNetCore
NLog.Extensions.Logging现在可以使用Microsoft Extension ConfigurationSection从appsettings.json加载NLog的配置,代码示例:
方式a:
注意代码:NLog.LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog"));
var config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
NLog.LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog"));
也可以这样:
方式b:
注意代码:.LoadConfigurationFromAppSettings()
Fluent API added with NLog.Web.AspNetCore ver. 4.9.3
Supports appsettings.json override by loading environment specific settings based on ASPNETCORE_ENVIRONMENT:
var logger = LogManager.Setup()
.LoadConfigurationFromAppSettings()
.GetCurrentClassLogger();
也可以这样:
方式c:
无需config.GetSection("NLog"),LoadConfigurationFromSection(config)会自动匹配Nlog配置的json字符串。
注意代码:.LoadConfigurationFromSection(config)
Manual loading of appsettings.json with fluent API:
var config = new ConfigurationBuilder()
.SetBasePath(basePath ?? Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{environment}.json", optional: true)
.AddEnvironmentVariables().Build();
var logger = LogManager.Setup()
.LoadConfigurationFromSection(config)
.GetCurrentClassLogger();
仔细看上面几种方式,可以知道,无论如何,你都要对配置文件进行加载,标红的注意代码,如果没有对配置文件加载,当然是不生效的。
3:nlog.config配置:
官方介绍有说到,Nlog会自动去加载配置文件,但有时平台需要显式的进行加载,代码示例:
NLog.LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration("nlog.config");
NLog v5引入了这种流畅的扩展方法:
NLog.LogManager.Setup().LoadConfigurationFromAssemblyResource(typeof(App).GetTypeInfo().Assembly);
更多的加载方式,官方都有说明,这里先介绍到此。
那么以上都是讲配置,如何在.net6的WPF项目中使用呢?
以下是官方的一段示例代码,我们从中去分析:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
static void Main(string[] args)
{
var logger = LogManager.GetCurrentClassLogger();
try
{
var config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory()) //From NuGet Package Microsoft.Extensions.Configuration.Json
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
using var servicesProvider = new ServiceCollection()
.AddTransient<Runner>() // Runner is the custom class
.AddLogging(loggingBuilder =>
{
// configure Logging with NLog
loggingBuilder.ClearProviders();
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
loggingBuilder.AddNLog(config);
}).BuildServiceProvider();
var runner = servicesProvider.GetRequiredService<Runner>();
runner.DoAction("Action1");
Console.WriteLine("Press ANY key to exit");
Console.ReadKey();
}
catch (Exception ex)
{
// NLog: catch any exception and log it.
logger.Error(ex, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
LogManager.Shutdown();
}
}
ServiceCollection类,我们就从这里入手,这个类刚好与文章开头的CommunityToolkit.Mvvm示例代码相符合,它便是我们配置应用程序服务的入口,因此可以这样将NLog服务注入:
services.AddLogging(builder =>
{
builder.ClearProviders();
builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
builder.AddNLog(config.GetSection("NLog"));//也可以直接丢config进来,NLog会自动根据关键字"NLog"进行解析
});
之后,我们就可以在任意类中通过DI的方式使用nlog输入日志了。
比如:
public class Runner
{
private readonly ILogger<Runner> _logger;
public Runner(ILogger<Runner> logger)
{
_logger = logger;
}
public void DoAction(string name)
{
_logger.LogDebug(20, "Doing hard work! {Action}", name);
}
}
至此,本文可以结束了。但我还想再说一点,以上是使用了 Microsoft Logging with Dependency Injection的方式,如果是想将一个logger服务对象放到某个IOC容器里如何做呢?
本文使用的IOC是CommunityToolkit.Mvvm.DependencyInjection.IOC
我们可以在配置ISericeCollection的时候,创建一个logger对象,同时从配置文件初始化Nlog对象,代码示例:
var loggerFactory = LoggerFactory.Create(builder => builder.AddNLog(configuration));
var logger = loggerFactory.CreateLogger("XXX任意名字,也可为空");
services.AddSingleton(logger);//将对象在容器中注册为单例
之后,我们就可以在任意类中,从IOC容器中使用该logger服务了,并且同样支持构造函数注入方式,比如:
注意:我们注册的是Microsoft.Extensions.Logging.ILogger,非NLog.ILogger
public class Runner
{
private readonly Microsoft.Extensions.Logging.ILogger _logger;
public Runner()
{
_logger = Ioc.Default.GetService<ILogger>();
}
public void DoAction(string name)
{
_logger.LogDebug(20, "Doing hard work! {Action}", name);
}
}
然后创建一个扩展方法:
public static void AddNlogService(this IServiceCollection services, IConfiguration configuration)
{
var loggerFactory = LoggerFactory.Create(builder => builder.AddNLog(configuration));
var logger = loggerFactory.CreateLogger("XXX任意名字,也可为空");
services.AddSingleton(logger);//方式1
//这两种方式用一个就可以了
services.AddLogging(builder =>
{
builder.ClearProviders();
builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
builder.AddNLog(config);
});//方式2
}
最初的配置服务代码,再这么改一下,就大功告成了!
/// <summary>
/// Configures the services for the application.
/// </summary>
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
var appConfig = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory()) //From NuGet Package Microsoft.Extensions.Configuration.Json
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
services.AddSingleton<IFilesService, FilesService>();
services.AddNlogSetup(appConfig);//添加日志服务
return services.BuildServiceProvider();
}
参考:
Configure from code · NLog/NLog Wiki · GitHub
NLog configuration with appsettings.json · NLog/NLog.Extensions.Logging Wiki · GitHub
Explicit NLog configuration loading · NLog/NLog Wiki · GitHub
Configuration file · NLog/NLog Wiki · GitHub
NLog GetCurrentClassLogger and Microsoft ILogger · NLog/NLog.Extensions.Logging Wiki · GitHub
https://learn.microsoft.com/zh-cn/dotnet/communitytoolkit/mvvm/ioc