.NET Core 配置系统与日志系统整理

.NET Core 配置系统与日志系统整理 .NET Core 配置系统与日志系统整理本文档整理了.NET Core中配置系统和日志系统的核心使用方法、关键包、实现步骤及高级特性涵盖基础操作、进阶用法和第三方组件集成是.NET Core开发中配置与日志管理的核心参考。一、配置系统.NET Core配置系统摒弃了传统Web.config支持多源配置JSON/XML/INI、环境变量、命令行等提供直接读取、对象绑定、选项方式推荐三种读取方式核心依赖Microsoft.Extensions.Configuration系列包。1. 核心基础准备1必备NuGet包功能包名配置系统核心Microsoft.Extensions.Configuration读取JSON配置文件Microsoft.Extensions.Configuration.Json配置绑定到实体类Microsoft.Extensions.Configuration.Binder选项方式依赖注入Microsoft.Extensions.Options Microsoft.Extensions.DependencyInjection2配置文件基础设置项目根目录添加配置文件如config.json/appsettings.json右键文件→属性→复制到输出目录设置为如果较新则复制运行时读取exe同级目录的配置文件修改后需重新生成项目。2. 三种读取配置的方式1直接读取IConfigurationRoot核心通过ConfigurationBuilder构建配置根对象直接通过键名/冒号分隔的分级键读取支持数据库连接字符串专用方法。// 1. 构建配置 var configBuilder new ConfigurationBuilder(); configBuilder.AddJsonFile(config.json, optional: false, reloadOnChange: true); IConfigurationRoot config configBuilder.Build(); // 2. 读取普通配置 string name config[name]!; string proxyAddr config.GetSection(proxy:address).Value!; // 3. 读取数据库连接字符串专用节点ConnectionStrings string connStr config.GetConnectionString(str);optional: false配置文件不存在时程序报错便于排查路径/文件名错误reloadOnChange: true配置文件修改后自动重新加载。2绑定方式读取核心将配置节点自动映射到自定义实体类避免逐个读取键值适用于配置项较多的场景。定义属性名与配置节点完全一致的实体类通过GetSection(节点名).Get实体类()或config.Get根实体类()完成绑定。// 定义实体类属性名与配置一致类名随意 public class Proxy { public string? address { get; set; } public int port { get; set; } } public class ConStr { public string? str { get; set; } } public class Config { public string? name { get; set; } public Proxy? proxy { get; set; } public ConStr? ConnectionStrings { get; set; } } // 绑定并读取 Config c config.GetConfig()!; Console.WriteLine(c.name c.proxy?.address c.ConnectionStrings!.str);3选项方式读取推荐核心结合依赖注入DI和配置自动刷新是.NET Core官方推荐方式封装了绑定方式支持三种泛型接口处理配置生命周期。① 三个核心泛型接口区别接口配置刷新特性适用场景IOptions不支持刷新需重启程序启动后不再修改的配置资源占用最少IOptionsMonitor实时刷新同一范围可读取新值无需保证范围配置一致性的场景易引发业务混乱IOptionsSnapshot范围内一致新范围读取新值大部分业务场景推荐保证单次请求/方法内配置一致示例单次方法中配置修改IOptionsMonitor会导致读写用不同配置IOptionsSnapshot则保持一致避免业务异常。② 实现步骤定义配置实体类如DBSettings/SmtpSettings匹配appsettings.json节点构建配置根对象配置DI容器注册选项和自定义类通过构造函数注入泛型接口读取配置值新范围读取新配置通过CreateScope()创建新DI范围实现配置刷新。// 1. 定义实体类 public class DBSettings { public string? DbType { get; set; } public string? ConnectionString { get; set; } } public class SmtpSettings { public string? Server { get; set; } public string? UserName { get; set; } public string? Password { get; set; } } // 2. 自定义类构造函数注入IOptionsSnapshotT public class ConfigDemo { private readonly IOptionsSnapshotDBSettings _optDb; private readonly IOptionsSnapshotSmtpSettings _optSmtp; public ConfigDemo(IOptionsSnapshotDBSettings optDb, IOptionsSnapshotSmtpSettings optSmtp) { _optDb optDb; _optSmtp optSmtp; } public void Run() { Console.WriteLine(_optDb.Value.DbType _optDb.Value.ConnectionString); Console.WriteLine(_optSmtp.Value.Server _optSmtp.Value.UserName); } } // 3. 主程序配置DI并调用 var configBuilder new ConfigurationBuilder(); configBuilder.AddJsonFile(appsettings.json, optional: false, reloadOnChange: true); IConfigurationRoot config configBuilder.Build(); // 注册DI服务 var services new ServiceCollection(); services.AddOptions() .ConfigureDBSettings(c config.GetSection(DB).Bind(c)) .ConfigureSmtpSettings(s config.GetSection(Smtp).Bind(s)); services.AddScopedConfigDemo(); // 创建容器循环读取新范围刷新配置 using (var sp services.BuildServiceProvider()) { while (true) { using (var scope sp.CreateScope()) { // 新范围 var demo scope.ServiceProvider.GetRequiredServiceConfigDemo(); demo.Run(); } Console.ReadKey(); } }二、日志系统日志是程序的“黑匣子”.NET Core提供内置日志框架支持控制台输出可集成NLog/Log4Net/Serilog等第三方组件实现日志持久化文件/数据库/邮件核心依赖Microsoft.Extensions.Logging系列包。1. 核心基础1日志级别从低到高级别描述适用场景Trace最详细信息含敏感数据开发调试生产环境禁用Debug开发调试短期有用信息开发阶段排查问题Information程序常规流程跟踪记录正常操作如“开始连接数据库”Warning潜在问题未影响运行记录重试操作如“第一次数据库连接失败”Error错误功能无法正常执行记录操作失败如“数据库连接失败”Critical致命错误系统即将崩溃记录严重故障如“服务器磁盘满”使用原则按操作结果分级如数据库连接→3次重试Information开始→Warning重试→Error失败。2必备NuGet包功能包名日志系统核心Microsoft.Extensions.Logging控制台输出日志Microsoft.Extensions.Logging.Console集成NLogNLog.Extensions.Logging2. 内置日志控制台输出核心通过DI注入日志服务使用泛型ILoggerT为当前类便于定位日志来源不支持非泛型ILogger注入。实现步骤安装核心包配置DI容器注册日志服务并指定输出到控制台构造函数注入ILoggerT调用日志方法输出不同级别信息可选设置日志最小级别过滤低级别日志。// 1. 配置DI var services new ServiceCollection(); services.AddLogging(logBuilder { logBuilder.AddConsole(); // 输出到控制台 logBuilder.SetMinimumLevel(LogLevel.Error); // 只输出Error及以上级别 }); // 2. 自定义类注入日志 public class TestLog { private readonly ILoggerTestLog _logger; public TestLog(ILoggerTestLog logger) { _logger logger; } public void ConnectSql() { _logger.LogInformation(开始连接数据库); _logger.LogWarning(第一次连接失败); _logger.LogError(数据库连接失败); // 占位符异常记录 try { int.Parse(abc); } catch (Exception ex) { _logger.LogError(ex, 类型转换失败); } } } // 3. 注册并调用 services.AddScopedTestLog(); using (var sp services.BuildServiceProvider()) { var testLog sp.GetRequiredServiceTestLog(); testLog.ConnectSql(); }3. 第三方日志NLog文件控制台推荐内置日志仅控制台输出无持久化NLog是轻量、强大的第三方日志组件支持日志分类、文件分割、级别过滤可输出到文件/控制台/数据库/邮件等。核心优势日志持久化到文件支持按日期/大小分割细粒度日志分类按模块/级别分文件配置文件自动重载无需重启程序限制日志文件数量和大小防止磁盘占满。4. NLog基本使用实现步骤安装NuGet包Microsoft.Extensions.LoggingNLog.Extensions.Logging项目根目录添加nlog.config配置文件设置复制到输出目录如果较新则复制配置DI容器替换日志输出为NLog运行程序日志自动输出到exe同级目录的文件和控制台。核心nlog.config配置基础版?xml version1.0 encodingutf-8 ? nlog xmlnshttp://www.nlog-project.org/schemas/NLog.xsd xsi:schemaLocationNLog NLog.xsd xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance autoReloadtrue !-- 配置修改自动重载 -- internalLogLeveloff !-- 关闭NLog自身日志 -- internalLogFilenlog-internal.log !-- 日志输出目标文件控制台 -- targets !-- 文件输出按日期命名指定日志格式 -- target xsi:typeFile namelogfile fileNamelogs/log-${shortdate}.log layout${longdate}|${level}|${message}|${exception:formattostring} / !-- 控制台输出 -- target xsi:typeConsole namelogconsole layout${longdate}|${level}|${message}|${exception:formattostring} / /targets !-- 日志输出规则所有日志输出到文件控制台最低级别Trace -- rules logger name* minlevelTrace writeTologfile,logconsole / /rules /nlog主程序代码var services new ServiceCollection(); services.AddLogging(logBuilder logBuilder.AddNLog()); // 替换为NLog services.AddScopedTestLog(); using (var sp services.BuildServiceProvider()) { var testLog sp.GetRequiredServiceTestLog(); testLog.ConnectSql(); }5. NLog高级特性分类过滤文件限制1核心特性日志分类按命名空间/模块分文件如登录模块、文件模块各一个日志文件日志过滤按级别/模块设置输出规则支持finaltrue匹配后不再执行后续规则文件限制archiveAboveSize单个文件最大字节、maxArchiveFiles最大文件数自动删除旧文件。2高级配置示例nlog.confignlog autoReloadtrue internalLogLeveloff targets !-- 通用日志TestLog类ConsoleApp命名空间按日期分文件 -- target xsi:typeFile namelogfile fileNamelogs/log-${shortdate}.log layout${longdate}|${level}|${message}|${exception} / !-- 系统文件模块日志SystemFile命名空间限制单个10KB最多3个文件 -- target xsi:typeFile namesysFileLog fileNamelogs/sysFile-${shortdate}.log archiveAboveSize10240 !-- 10KB -- maxArchiveFiles3 !-- 最多3个 -- layout${longdate}|${level}|${message}|${exception} / !-- 控制台输出只显示Warn及以上级别 -- target xsi:typeConsole namelogconsole layout${longdate}|${level}|${message} / /targets rules !-- 规则1所有模块Warn-Fatal级别输出到控制台 -- logger name* minlevelWarn maxlevelFatal writeTologconsole / !-- 规则2SystemFile命名空间所有级别输出到sysFileLogfinaltrue不再匹配后续 -- logger nameSystemFile.* minlevelTrace writeTosysFileLog finaltrue / !-- 规则3其他所有模块所有级别输出到logfile -- logger name* minlevelTrace writeTologfile / /rules /nlog3使用注意若使用NLog的分级/过滤注释掉.NET内置的SetMinimumLevel避免冲突命名空间作为分类标识不同模块放在不同命名空间便于日志隔离日志文件路径为exe同级目录可通过绝对路径指定自定义目录。