- UI组件
- 桌面应用
【免费下载链接】SunnyUI
SunnyUI.NET 是基于.NET Framework 4.0+、.NET6、.NET8、.NET9 框架的 C# WinForm UI、开源控件库、工具类库、扩展类库、多页面开发框架。
SunnyUI 的IniConfig<T>是构建在 IniFile - Ini文件读写类 之上的高级配置类:它通过反射把 INI 文件的 Section/Key 自动映射到类的属性上,开发者只需写一个继承IniConfig<T>的配置类,即可完成配置的读取、默认值初始化与保存,彻底摆脱手工拼接 section、name 字符串的繁琐过程。读完本文,你将掌握IniConfig的核心原理、特性(Attribute)用法、Load/Save生命周期以及 UTF-8 场景下的IniUTF8Config方案。
为什么需要 IniConfig:从 IniFile 的痛点说起
先回顾一下 IniFile - Ini文件读写类 的基本用法。写文件:
IniFile ini = new IniFile("D:\\setup.ini"); ini.Write("Setup", "Name", "Sunny"); ini.Write("Setup", "Age", 18); ini.UpdateFile();读文件:
IniFile ini = new IniFile("D:\\setup.ini"); string name = ini.ReadString("Setup", "Name", ""); int age = ini.ReadInt("Setup", "Age", 0);这种方式虽然直观,但有明显不便:你必须自己知道配置文件的位置,并正确填写 section 与 name 的字符串,读写的每个参数都要写一行代码,且字符串拼写极易出错。IniConfig正是为了解决这个问题而设计——只要在类上写好属性,就可以直接使用,而不用关注底层读写细节。
原理:反射 + INI 存储
IniConfig<T>的核心原理在 UIniConfig.cs 和 UBaseConfig.cs 中有完整实现:
- 反射收集属性:
ConfigHelper.InitIdents通过Type.GetProperties()获取配置类的全部属性,剔除带忽略特性(XmlIgnore、ConfigIgnore、MapperIgnore、Ignore)的属性,并为每个属性生成一个Ident节点(包含 Section、Key、Description、Index、IsList 等元数据)。 - Section 默认值:如果属性未标注
ConfigSection特性,其 Section 会被自动赋值为"Setup"(见IniConfig.Load/Save中的ident.Section = "Setup"逻辑)。 - 映射读写:加载时通过
ini.Read(ident.Section, ident.Key, "")逐项读取,再用ConfigHelper.LoadConfigValue把字符串按属性类型转换回对象(ConvertEx.StringToObject);保存时用ConfigHelper.SaveConfigValue把属性值转换回字符串,再按 Section 分组、按Index排序写入文件。
因此从源码结构看,IniConfig的读写完全由「特性元数据 + 反射」驱动,IniFile仅作为底层存储引擎。
快速上手:定义一个配置类
原文档给出了一个典型场景——保存服务器地址、端口、软件名称以及天气城市。配置类代码如下:
[ConfigFile("Config\\Setting.ini")] public class Setting : IniConfig<Setting> { [ConfigSection("Hello")] public string SoftName { get; set; } public string ServerIP { get; set; } public int ServerPort { get; set; } public string City { get; set; } public override void SetDefault() { base.SetDefault(); SoftName = "XX软件"; ServerIP = "192.168.1.2"; ServerPort = 9090; City = "南京"; } }几个关键点:
[ConfigFile("Config\\Setting.ini")]:指定 INI 文件位置,即当前程序目录下Config目录中的Setting.ini。目录不存在时会自动创建(源码中Dir.CreateDir(Path.GetDirectoryName(filename))保证了这一点)。若类上完全没有该特性,ConfigHelper.GetConfigFile会回退为默认文件名{类名}.cfg,例如Setting.cfg。[ConfigSection("Hello")]:设置SoftName所属的 Section 名称;不设置则默认为Setup。public override void SetDefault():当第一次运行、配置文件不存在时,为配置设置默认值,并保存至文件。注意基类BaseConfig<T>.SetDefault()是虚方法且默认空实现,重写时建议先调用base.SetDefault()。
首次运行后生成的Config\Setting.ini大致如下(文件头部由Save方法写入版本与编码信息,属性描述以;<!--...-->注释输出):
;<?Ini Version="..." Encoding="...?> ;<?Update Time="..."?> [Hello] SoftName=XX软件 [Setup] ServerIP=192.168.1.2 ServerPort=9090 City=南京特性(Attribute)一览:精细控制映射行为
围绕IniConfig,UBaseConfig.cs 定义了一套特性,用于控制配置的存储行为:
| 特性 | 作用对象 | 说明 |
|---|---|---|
ConfigFileAttribute | 类 | 指定配置文件路径(相对程序当前目录),构造函数ConfigFileAttribute(string fileName, string description = ""),description 可做配置描述 |
ConfigSectionAttribute | 属性 | 指定属性所属的 Section,ConfigSectionAttribute(string section),缺省时统一归入Setup |
ConfigPropertyAttribute | 属性 | 提供 Caption(标题)、Description(描述)、Unit(单位),用于展示与注释输出 |
ConfigIndexAttribute | 属性 | 指定写入顺序ConfigIndexAttribute(int index, bool show = true),未标注时按short.MaxValue后的追加次序排列 |
ConfigIgnoreAttribute | 属性 | 忽略此属性,不参与配置存储(IniEncoding等运行时属性即用此特性排除) |
IgnoreAttribute/MapperIgnoreAttribute | 属性 | 同样用于忽略属性,GetNeedProperties会一并跳过 |
XmlIgnoreAttribute | 属性 | 框架原生特性,同样被GetNeedProperties识别并跳过 |
属性描述信息:InitIdents会优先读取ConfigPropertyAttribute.Description,其次回退到DisplayNameAttribute或DescriptionAttribute,最终写入 INI 文件作为;<!--描述-->注释,让配置文件更具可读性。
读取配置:Setting.Current.Load()
配置类定义好后,读取系统配置并开始应用:
Setting.Current.Load(); TcpClient client = new TcpClient(); client.Connect(Setting.Current.ServerIP, Setting.Current.ServerPort);Setting.Current.Load():读取配置信息,将Setting.ini里的值读入类的属性中。此后Setting.Current.ServerIP、Setting.Current.ServerPort即可直接使用。- 如果需要修改配置,直接修改
Setting.ini,再重新调用读取即可。 - 注意:配置读取与属性的应用,都使用
Setting.Current,而不是Setting。
从源码看,BaseConfig<T>.Current是一个静态属性:首次访问时若内部current为空,会CreateNew()(内部先执行SetDefault()填充默认值)并尝试Load(CurrentDir() + ConfigFile);若文件不存在(Load 返回 false),则自动调用Save()把默认值落盘。这意味着你甚至可以跳过显式Load(),直接访问Setting.Current.xxx也能得到可用配置——首次访问即完成「默认值 + 建文件」的初始化。也可以把Current置空(set访问器)以强制下次重新加载。
保存配置:Setting.Current.Save()
系统内修改配置后,保存到配置文件。例如将获取天气的城市改为重庆:
Setting.Current.City = "重庆"; Setting.Current.Save();修改Setting.Current的属性,再调用Setting.Current.Save()即可完成持久化。Save内部通过ConfigHelper.SaveConfigValue把当前属性值序列化为字符串,按 Section 分组后以[Section]+Key=Value格式写出,并采用「先写临时文件、再替换」的策略保证写入安全(见 UIniConfig.cs 中filename + "." + RandomEx.RandomPureChar(3)临时文件逻辑)。若保存失败(例如目录无写权限),会弹出MessageBox提示“配置文件存储失败”。
进阶用法与注意事项
1. 建议使用 IniConfig 生成的文件,保证编码统一
通过IniConfig的应用,屏蔽了 ini 文件常用的「section、name 字符串取值」的繁琐过程。需要特别注意的是:建议读写 ini 文件为IniConfig存储的文件,先由程序生成文件再修改,而不是手动创建配置文件,以免造成文件编码不统一。IniBase默认以Encoding.Default读写,并对中文做了处理。
2. 始终使用 Setting.Current,而不是 Setting
配置读取、保存、属性应用全部经由Setting.Current这个静态单例实例,直接 new 一个Setting不会触发现有配置文件数据。Current还可被置空以触发重新加载。
3. 支持的属性类型
IniConfig支持的属性类型与IniFile一致,详见 IniFile - Ini文件读写类。IniFile在 WinAPIWritePrivateProfileString仅支持 string 的基础上,通过类型转换扩展支持:bool、byte、byte[]、char、Color、DateTime、decimal、double、float、int、long、Point、PointF、sbyte、short、Size、SizeF、uint、ulong、ushort以及Struct类型。在IniConfig的加载/保存流程中,数值、布尔、日期等基础类型通过ConvertEx.StringToObject/ObjectToString完成转换(见 UBaseConfig.cs 的LoadConfigValue/SaveConfigValue)。
4. UTF-8 编码:IniUTF8Config
如果希望配置文件的编码固定为 UTF-8(例如需要跨平台迁移或防止 Windows 系统代码页差异导致乱码),可以使用同文件提供的IniUTF8Config<T>(定义于 UIniConfig.cs)。它与IniConfig的用法完全一致,区别仅在于读写时固定使用Encoding.UTF8而不是Encoding.Default。
5. 配置加密
BaseConfig<T>还提供了Encrypt(string str)/Decrypt(string str)两个方法(见 UBaseConfig.cs),基于DesEncrypt/DesDecrypt对配置字符串做加解密,可用于密码等敏感字段的存储场景。
6. 指定编码与按属性名读写
IniConfig<T>还支持Load(string fileName, Encoding encoding)重载,通过传入编码加载指定路径的配置文件;同时提供了this[string property]索引器,可以按属性名称动态读取/写入属性值(见 UIniConfig.cs)。
小结
IniConfig<T>是 SunnyUI 为 WinForm 项目提供的“声明式”配置方案:把 INI 的 Section/Key 映射、类型转换、默认值初始化、文件自动创建全部收敛到特性与基类内部,业务代码只需要声明属性、重写SetDefault()、通过Setting.Current读写即可。对于追求轻量配置、又希望避免手写 XML/JSON 解析的项目,这是一个非常实用的开箱即用选择;如需底层 INI 格式的定义与手工读写 API,可继续阅读 IniFile - Ini文件读写类。
- UI组件
- 桌面应用
【免费下载链接】SunnyUI
SunnyUI.NET 是基于.NET Framework 4.0+、.NET6、.NET8、.NET9 框架的 C# WinForm UI、开源控件库、工具类库、扩展类库、多页面开发框架。
相关推荐
kfyty725/loveqq-framework的配置类:@ComponentScan属性详解
kfyty725/loveqq framework的配置类:@ComponentScan属性详解 你是否在使用loveqq framework框架时,对@Com
后端Web框架依赖注入桌面应用新手必看:读懂OpenMower的ROS软件架构——launch文件、参数系统与Topic/Service全景图
新手必看:读懂OpenMower的ROS软件架构——launch文件、参数系统与Topic/Service全景图 OpenMower 是一款开源的 DIY 智能
机器人智能硬件嵌入式Puerts 模板式静态绑定(Template-Based Static Binding):在 Unreal Engine 中把无反射标记的 C++ 类型接入 TypeScript
Puerts 模板式静态绑定(Template Based Static Binding):在 Unreal Engine 中把无反射标记的 C++ 类型接入
游戏开发跨平台
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考