PowerConfig 1.0.5
dotnet add package PowerConfig --version 1.0.5
NuGet\Install-Package PowerConfig -Version 1.0.5
<PackageReference Include="PowerConfig" Version="1.0.5" />
<PackageVersion Include="PowerConfig" Version="1.0.5" />
<PackageReference Include="PowerConfig" />
paket add PowerConfig --version 1.0.5
#r "nuget: PowerConfig, 1.0.5"
#:package PowerConfig@1.0.5
#addin nuget:?package=PowerConfig&version=1.0.5
#tool nuget:?package=PowerConfig&version=1.0.5
PowerConfig 使用说明书(1.05版)
欢迎使用 PowerConfig —— 一个为 .NET 应用程序设计的轻量级、零配置的动态 XML 配置库。它提供三种风格 API(静态方法、索引器、动态属性),支持无限层级嵌套,所有修改自动持久化到 pwrcfg.xml 文件中。
✨ 主要特性
- 零配置启动:首次使用自动生成配置文件,无需初始化。
- 三种风格 API:
- 静态方法:
Config.Set/Config.Get,适合键名动态生成的场景。 - 索引器:
Config.Root["key"],通过字符串键名访问,灵活且自然。 - 动态属性:
Config.Root.Level1.Level2 = value,像操作变量一样读写任意层级。
- 静态方法:
- 无限层级嵌套:任意层级的动态赋值都会自动创建中间节点,无需预定义结构。
- 短路缺失节点:当访问的节点路径中任何一级不存在时,立即返回
MissingNode,后续所有访问均不报错。 - 智能隐式转换:将动态属性赋值给
string变量时自动转换:- 叶子节点 → 存储的字符串值
- 容器节点 → 子节点数量统计,如
"2 children" - 缺失节点 →
"node or value not exist"
- 节点操作增强:
- 通过
.Node()方法获取叶子节点的节点对象,支持SetValue、Delete等操作。 - 支持通过索引值(如
Key(machineName))定位叶子节点并进行操作和删除。
- 通过
- 链式节点访问:通过
Config.Key获取节点对象,支持遍历子节点、判断存在性等。 - 自动持久化:每次修改立即保存到 XML 文件,无需手动调用
Save。 - 线程安全:内部锁保证多线程环境下的读写安全。
- 轻量级:仅依赖 .NET 内置库,无外部依赖。
- 多种访问方式:支持静态访问、注册全局访问、动态声明访问三种模式,适应不同场景。
📦 安装
通过 NuGet 安装(推荐)
dotnet add package PowerConfig
或直接引用 DLL
将编译后的 PowerConfig.dll 添加到项目引用,并在代码文件顶部添加:
using PowerConfig;
🚀 快速开始
1. 引入命名空间
using PowerConfig;
2. 写入配置(三种风格)
// 风格一:静态方法
Config.Set("AppName", "MyApp");
Config.Set("Database.Server", "localhost");
// 风格二:索引器(通过 Root)
Config.Root["Version"] = "1.0.0";
Config.Root["Database.Port"] = "1433";
// 风格三:动态属性(自动创建中间节点)
Config.Root.Database.Credentials.User = "sa";
Config.Root.Database.Credentials.Password = "123456";
Config.Root.Person.Name = "John";
Config.Root.Person.Address.City = "New York"; // 自动创建 Address 节点
3. 读取配置
// 叶子节点直接返回字符串
string appName = Config.Get("AppName"); // "MyApp"
string server = Config.Root.Database.Server; // "localhost"
// 容器节点返回统计信息
string yoloInfo = Config.Root.Database; // "2 children"
// 不存在的节点返回友好提示
string nonExist = Config.Root.Some.Nonexistent.Path; // "node or value not exist"
string deepNonExist = Config.Root.a.b.c.d.e.f; // "node or value not exist"
// 索引器方式(返回 null 或值)
string port = Config.Root["Database.Port"]; // "1433"
string missing = Config.Root["Some.Missing"]; // null
4. 生成的 XML 文件(pwrcfg.xml)
<Configuration>
<AppName>MyApp</AppName>
<Version>1.0.0</Version>
<Database>
<Server>localhost</Server>
<Port>1433</Port>
<Credentials>
<User>sa</User>
<Password>123456</Password>
</Credentials>
</Database>
<Person>
<Name>John</Name>
<Address>
<City>New York</City>
</Address>
</Person>
</Configuration>
🧰 API 详解
静态类 Config
| 成员 | 描述 |
|---|---|
dynamic Root |
动态根对象,用于动态属性赋值和索引器访问。 |
dynamic Dynamic |
兼容旧版的别名,指向同一实例。 |
void Set(string key, string value) |
通过点号路径设置值(如 "Database.Server")。 |
string Get(string key) |
通过点号路径获取值,不存在返回 null。 |
IEnumerable<string> GetKeys() |
获取所有顶级键名。 |
bool ContainsKey(string key) |
判断指定路径的节点是否存在(作为叶子或容器)。 |
ConfigNodeBase Key(string path) |
获取节点对象,用于链式遍历。 |
节点基类 ConfigNodeBase
所有动态属性返回的对象都派生自此类,包含以下成员:
| 成员 | 描述 |
|---|---|
ConfigNodeBase Key(string name) |
获取子节点代理。 |
IEnumerable<string> GetKeys() |
获取当前节点下的直接子键名。 |
void SetValue(string value) |
设置当前节点的值(会使其成为叶子)。 |
bool Exists() |
判断当前节点是否存在。 |
ConfigNodeBase Node() |
获取当前节点的节点对象(用于节点操作)。对于叶子节点,返回其节点对象;对于容器节点,返回自身。 |
void Delete() |
删除当前节点(物理删除)。 |
override string ToString() |
返回字符串表示(与隐式转换相同)。 |
static implicit operator string(ConfigNodeBase node) |
隐式转换为字符串。 |
隐式转换规则
将节点对象赋值给 string 变量时自动触发:
| 节点类型 | 转换结果 |
|---|---|
| 叶子节点 | 存储的字符串值 |
| 容器节点 | "{n} children"(n 为直接子节点数量) |
| 缺失节点 | "node or value not exist" |
📘 常见使用案例
1. 动态属性赋值与读取
Config.Root.User.Name = "Alice";
Config.Root.User.Email = "alice@example.com";
string name = Config.Root.User.Name; // "Alice"
string email = Config.Root.User.Email; // "alice@example.com"
string userInfo = Config.Root.User; // "2 children"
2. 遍历 Database 下的所有子属性
var dbNode = Config.Key("Database");
if (dbNode.Exists())
{
Console.WriteLine($"Database has {dbNode}"); // 隐式转换,如 "Database has 2 children"
foreach (var key in dbNode.GetKeys())
{
var child = dbNode.Key(key);
if (child.GetKeys().Any())
Console.WriteLine($" {key}/ ({child})");
else
Console.WriteLine($" {key} = {child}");
}
}
3. 递归遍历所有配置
void Traverse(ConfigNodeBase node, string indent = "")
{
foreach (var key in node.GetKeys())
{
var child = node.Key(key);
if (child.GetKeys().Any())
{
Console.WriteLine($"{indent}{key}/ ({child})");
Traverse(child, indent + " ");
}
else
{
Console.WriteLine($"{indent}{key} = {child}");
}
}
}
Traverse(Config.Key(""));
4. 使用默认值
int port = int.Parse(Config.Get("Database.Port") ?? "1433");
// 或通过动态属性 + 隐式转换
string portStr = Config.Root.Database.Port; // 如果不存在,返回 "node or value not exist"
if (portStr != "node or value not exist" && int.TryParse(portStr, out int p))
port = p;
else
port = 1433;
5. 修改深层节点的值
Config.Key("Database").Key("Port").SetValue("5432");
// 或直接动态属性赋值
Config.Root.Database.Port = "5432";
6. 检查节点是否存在
if (Config.Key("Database.Credentials").Exists())
{
// 存在
}
7. 给缺失节点赋值(自动创建)
Config.Root.NewSection.NewSubSection.Value = "created";
string val = Config.Root.NewSection.NewSubSection.Value; // "created"
8. 安全读取不存在节点(无需 try-catch)
string result = Config.Root.A.B.C.D.E.F; // 永远返回 "node or value not exist"
🆕 节点操作增强:叶子节点操作与删除
9. 通过 .Node() 操作叶子节点
PowerConfig 的链式访问在叶子节点处返回 string,方便直接读取值。但当需要对叶子节点进行节点操作(如修改值、删除)时,可以使用 .Node() 方法获取节点对象。
示例:设置叶子节点的值
// 假设 XML 中已有 StateMachineManager.ManagerState 节点
// 直接读取值
string currentState = Config.Root.StateMachineManager.ManagerState; // 返回字符串
// 通过 .Node() 获取节点对象并设置值
Config.Root.StateMachineManager.ManagerState.Node().SetValue("Running");
// 再次读取验证
string newState = Config.Root.StateMachineManager.ManagerState; // "Running"
示例:删除叶子节点
// 删除 ManagerState 节点(物理删除)
Config.Root.StateMachineManager.ManagerState.Node().Delete();
// 此时再访问该节点,返回 "node or value not exist"
string deletedState = Config.Root.StateMachineManager.ManagerState; // "node or value not exist"
10. 通过索引值(Key() 方法)操作叶子节点
当叶子节点的名称是动态的(如机器名、ID 等),可以通过 Key() 方法定位并进行操作。
示例:设置动态叶子节点的值
string machineName = "PrinterServer";
// 通过 Key() 方法定位到叶子节点并设置值
Config.Root.StateMachineManager.Key(machineName).SetValue("Running");
// 读取值
string state = Config.Root.StateMachineManager.Key(machineName).GetValue(); // "Running"
示例:删除动态叶子节点
string machineName = "PrinterServer";
// 通过 Key() 定位并删除
Config.Root.StateMachineManager.Key(machineName).Delete();
// 验证删除
string deletedState = Config.Root.StateMachineManager.Key(machineName).GetValue(); // null
11. 结合 .Node() 和 Key() 操作动态叶子节点
对于通过 Key() 获取的节点,可以进一步调用 .Node()(实际上 Key() 返回的已经是节点对象,无需再调用 .Node(),但为了一致性也可以调用)。
string machineName = "PrinterServer";
// Key() 返回的是 ConfigNodeBase,可以直接调用 SetValue
Config.Root.StateMachineManager.Key(machineName).SetValue("Idle");
// 或者通过 .Node()(等效)
Config.Root.StateMachineManager.Key(machineName).Node().SetValue("Busy");
// 读取值
string state = Config.Root.StateMachineManager.Key(machineName).GetValue(); // "Busy"
12. 容器节点的删除
删除容器节点时,其所有子节点也会被一并删除。
// 删除整个 StateMachineManager 容器
Config.Root.StateMachineManager.Node().Delete();
// 验证删除
string deleted = Config.Root.StateMachineManager; // "node or value not exist"
13. 使用静态方法操作动态叶子节点
静态方法 Config.Set 和 Config.Get 是最可靠的方式,尤其适合动态键名。
string machineName = "PrinterServer";
// 设置值
Config.Set($"StateMachineManager.{machineName}", "Running");
// 读取值
string state = Config.Get($"StateMachineManager.{machineName}"); // "Running"
// 删除节点(通过设置为 null 或空字符串)
Config.Set($"StateMachineManager.{machineName}", null);
// 注意:Set 方法不会物理删除节点,只会清空值。如需物理删除,请使用 Delete() 方法。
🆕 三种访问方式详解
PowerConfig 提供了三种访问方式,以适应不同的应用场景:
方式一:纯粹静态访问(PConfig)
直接使用 PConfig,无需任何注册或声明,整个工程随处可用。
// 写入
PConfig.Root.AppName = "MyApp";
PConfig.Set("Database.Server", "localhost");
// 读取
string name = PConfig.Root.AppName;
string server = PConfig.Get("Database.Server");
特点:
- 零配置,开箱即用
- 全局静态,随处可访
- 配置文件固定为
pwrcfg.xml
方式二:注册后全局访问(ConfigContext)
通过 ConfigContext 注册命名配置实例,注册后可在整个工程中通过名称全局访问。
// 在 Program.cs 或启动处注册
ConfigContext.GetOrCreate("app1", "app1.xml");
ConfigContext.GetOrCreate("app2", "app2.xml");
// 任何窗体、任何类中都可以通过名称访问
var app1 = ConfigContext.Get("app1");
app1.Root.AppName = "App1 Name";
var app2 = ConfigContext.Get("app2");
app2.Root.AppName = "App2 Name";
特点:
- 支持多个配置文件共存
- 注册后全局访问,跨窗体/跨类共享
- 线程安全,每个名称对应一个单例实例
- 适合多环境配置(如开发/生产)、多模块配置
方式三:动态声明访问(ConfigBuilder)
通过 ConfigBuilder 创建独立实例,不注册到全局,通常用于局部或一次性场景。
// 创建独立实例
var customConfig = new ConfigBuilder()
.UseFile("temp.xml")
.Build();
// 局部使用
customConfig.Root.TempData = "temporary";
string data = customConfig.Root.TempData;
// 该实例不会被其他类共享
特点:
- 完全独立,不污染全局
- 适合临时配置、单元测试
- 生命周期由使用者控制
- 不与其他实例共享
三种访问方式对比
| 特性 | 静态访问(PConfig) | 注册全局访问(ConfigContext) | 动态声明访问(ConfigBuilder) |
|---|---|---|---|
| 配置文件名 | 固定 pwrcfg.xml |
自定义 | 自定义 |
| 是否需注册 | ❌ 不需要 | ✅ 需要 GetOrCreate |
❌ 不需要 |
| 全局共享 | ✅ 是 | ✅ 是 | ❌ 否 |
| 多配置共存 | ❌ 否 | ✅ 是 | ✅ 是 |
| 跨窗体使用 | ✅ 可直接使用 | ✅ 通过 Get(name) 获取 |
❌ 需要传递实例 |
| 适用场景 | 单一配置的应用 | 多配置/多环境应用 | 临时/测试场景 |
⚠️ 注意事项
- 所有值均为字符串:存储时自动转为字符串,读取后需自行转换类型。
- 动态属性赋值规则:
- 给叶子节点赋字符串值:正常更新。
- 给容器节点赋字符串值:节点变为叶子,原有子节点全部丢失。
- 给缺失节点赋字符串值:自动创建所有中间节点,并设置叶子值。
- 隐式转换:将动态属性赋值给
string变量时自动触发,无需显式调用方法。 - 节点操作:
- 叶子节点通过
.Node()获取节点对象后,可调用SetValue、Delete等方法。 Key()方法返回的节点对象可直接调用SetValue、Delete等方法。Delete()方法会物理删除节点及其所有子节点,请谨慎使用。
- 叶子节点通过
- 线程安全:所有公共方法都是线程安全的。
- 配置文件位置:默认保存在应用程序工作目录(
Environment.CurrentDirectory),文件名为pwrcfg.xml。 - 键名区分大小写:
"Database.Server"与"database.server"不同。
🤝 贡献与许可
PowerConfig 采用 MIT 许可证,欢迎提交 Issue 或 Pull Request。
感谢您使用 PowerConfig!
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.