PowerConfig 1.0.5

dotnet add package PowerConfig --version 1.0.5
                    
NuGet\Install-Package PowerConfig -Version 1.0.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PowerConfig" Version="1.0.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PowerConfig" Version="1.0.5" />
                    
Directory.Packages.props
<PackageReference Include="PowerConfig" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PowerConfig --version 1.0.5
                    
#r "nuget: PowerConfig, 1.0.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PowerConfig@1.0.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PowerConfig&version=1.0.5
                    
Install as a Cake Addin
#tool nuget:?package=PowerConfig&version=1.0.5
                    
Install as a Cake Tool

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() 方法获取叶子节点的节点对象,支持 SetValueDelete 等操作。
    • 支持通过索引值(如 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.SetConfig.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() 获取节点对象后,可调用 SetValueDelete 等方法。
    • Key() 方法返回的节点对象可直接调用 SetValueDelete 等方法。
    • Delete() 方法会物理删除节点及其所有子节点,请谨慎使用。
  • 线程安全:所有公共方法都是线程安全的。
  • 配置文件位置:默认保存在应用程序工作目录(Environment.CurrentDirectory),文件名为 pwrcfg.xml
  • 键名区分大小写"Database.Server""database.server" 不同。

🤝 贡献与许可

PowerConfig 采用 MIT 许可证,欢迎提交 Issue 或 Pull Request。

感谢您使用 PowerConfig!

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • 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.

Version Downloads Last Updated
1.0.5 90 6/17/2026
1.0.4 126 3/15/2026