|
|
1 день назад | |
|---|---|---|
| .workflow | 5 дней назад | |
| Apq.Cfg | 1 день назад | |
| Apq.Cfg.Database | 1 день назад | |
| Apq.Cfg.Ini | 1 день назад | |
| Apq.Cfg.Redis | 1 день назад | |
| Apq.Cfg.Toml | 1 день назад | |
| Apq.Cfg.Xml | 1 день назад | |
| Apq.Cfg.Yaml | 1 день назад | |
| Samples | 5 дней назад | |
| benchmarks | 1 день назад | |
| buildTools | 2 дней назад | |
| doc | 2 дней назад | |
| tests | 2 дней назад | |
| versions | 1 день назад | |
| .gitignore | 1 день назад | |
| Apq.Cfg.sln | 3 дней назад | |
| Directory.Build.props | 1 день назад | |
| LICENSE | 6 дней назад | |
| README.md | 1 день назад |
统一配置管理系统,支持多种配置格式和多层级配置合并。
仓库地址:https://gitee.com/apq/Apq.Cfg
Apq.Cfg/
├── Apq.Cfg/ # 核心库(JSON + 环境变量)
├── Apq.Cfg.Ini/ # INI 文件扩展
├── Apq.Cfg.Xml/ # XML 文件扩展
├── Apq.Cfg.Yaml/ # YAML 文件扩展
├── Apq.Cfg.Toml/ # TOML 文件扩展
├── Apq.Cfg.Redis/ # Redis 扩展
├── Apq.Cfg.Database/ # 数据库扩展
├── Samples/ # 示例项目
│ └── Apq.Cfg.Samples/
├── tests/ # 单元测试
│ ├── Apq.Cfg.Tests.Shared/ # 共享测试代码
│ ├── Apq.Cfg.Tests.Net6/ # .NET 6 测试项目
│ ├── Apq.Cfg.Tests.Net8/ # .NET 8 测试项目
│ └── Apq.Cfg.Tests.Net9/ # .NET 9 测试项目
├── benchmarks/ # 性能测试
│ └── Apq.Cfg.Benchmarks/ # 性能测试项目(多目标框架)
├── buildTools/ # 构建工具脚本
├── versions/ # 版本文件目录
└── nupkgs/ # NuGet 包输出目录
.NET 6.0 / 7.0 / 8.0 / 9.0
using Apq.Cfg;
var cfg = new CfgBuilder()
.AddJson("appsettings.json", level: 0, writeable: false)
.AddJson("appsettings.local.json", level: 1, writeable: true, isPrimaryWriter: true)
.AddEnvironmentVariables(level: 2, prefix: "APP_")
.Build();
// 读取配置
var value = cfg.Get("Database:ConnectionString");
// 修改配置
cfg.Set("App:LastRun", DateTime.Now.ToString());
await cfg.SaveAsync();
支持配置文件变更时自动更新,无需重启应用:
using Apq.Cfg;
using Apq.Cfg.Changes;
using Microsoft.Extensions.Primitives;
// 构建配置(启用 reloadOnChange)
var cfg = new CfgBuilder()
.AddJson("appsettings.json", level: 0, writeable: false, reloadOnChange: true)
.AddJson("appsettings.local.json", level: 1, writeable: true, reloadOnChange: true)
.AddEnvironmentVariables(level: 2, prefix: "APP_")
.Build();
// 获取支持动态重载的 Microsoft Configuration
var msConfig = cfg.ToMicrosoftConfiguration(new DynamicReloadOptions
{
DebounceMs = 100, // 防抖时间窗口(毫秒)
EnableDynamicReload = true // 启用动态重载
});
// 方式1:使用 IChangeToken 监听变更
ChangeToken.OnChange(
() => msConfig.GetReloadToken(),
() => Console.WriteLine("配置已更新"));
// 方式2:使用 Rx 订阅配置变更事件
cfg.ConfigChanges.Subscribe(e =>
{
foreach (var (key, change) in e.Changes)
{
Console.WriteLine($"[{change.Type}] {key}: {change.OldValue} -> {change.NewValue}");
}
});
# 构建
dotnet build
# 运行单元测试
dotnet test
# 运行性能测试(需要管理员权限以获得准确结果)
cd benchmarks/Apq.Cfg.Benchmarks
dotnet run -c Release
| 测试类 | 测试数量 | 说明 |
|---|---|---|
| JsonCfgTests | 15 | JSON 配置源测试 |
| EnvVarsCfgTests | 4 | 环境变量配置源测试 |
| IniCfgTests | 5 | INI 文件配置源测试 |
| XmlCfgTests | 5 | XML 文件配置源测试 |
| YamlCfgTests | 6 | YAML 文件配置源测试 |
| TomlCfgTests | 6 | TOML 文件配置源测试 |
| RedisCfgTests | 5 | Redis 配置源测试 |
| DatabaseCfgTests | 5 | 数据库配置源测试 |
| CfgRootExtensionsTests | 4 | 扩展方法测试 |
| CfgBuilderAdvancedTests | 14 | 高级功能测试 |
| DynamicReloadTests | 12 | 动态配置重载测试 |
| EncodingDetectionTests | 14 | 编码检测测试 |
| ConcurrencyTests | 10 | 并发安全测试 |
| BoundaryConditionTests | 32 | 边界条件测试 |
| ExceptionHandlingTests | 20 | 异常处理测试 |
| ConfigChangesSubscriptionTests | 28 | 配置变更订阅测试 |
| API | Json | Env | Ini | Xml | Yaml | Toml | Redis | DB |
|---|---|---|---|---|---|---|---|---|
| ICfgRoot | ||||||||
Get(key) |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Get<T>(key) |
✅ | - | ✅ | ✅ | ✅ | ✅ | - | - |
Exists(key) |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Set(key, value) |
✅ | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Set(key, value, targetLevel) |
✅ | - | - | - | - | - | - | - |
Remove(key) |
✅ | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Remove(key, targetLevel) |
✅ | - | - | - | - | - | - | - |
SaveAsync() |
✅ | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
SaveAsync(targetLevel) |
✅ | - | - | - | - | - | - | - |
ToMicrosoftConfiguration() |
✅ | - | - | - | - | - | - | - |
ToMicrosoftConfiguration(options) |
✅ | - | - | - | - | - | - | - |
ConfigChanges |
✅ | - | - | - | - | - | - | - |
Dispose/DisposeAsync |
✅ | - | - | - | - | - | - | - |
| CfgBuilder | ||||||||
AddJson() |
✅ | - | - | - | - | - | - | - |
AddEnvironmentVariables() |
- | ✅ | - | - | - | - | - | - |
WithEncodingConfidenceThreshold() |
✅ | - | - | - | - | - | - | - |
Build() |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| CfgRootExtensions | ||||||||
TryGet<T>() |
✅ | - | - | - | - | - | - | - |
GetRequired<T>() |
✅ | - | - | - | - | - | - | - |
| FileCfgSourceBase | ||||||||
WriteEncoding |
✅ | - | - | - | - | - | - | - |
EncodingConfidenceThreshold |
✅ | - | - | - | - | - | - | - |
DetectEncoding() |
✅ | - | - | - | - | - | - | - |
| 扩展包 | ||||||||
AddIni() |
- | - | ✅ | - | - | - | - | - |
AddXml() |
- | - | - | ✅ | - | - | - | - |
AddYaml() |
- | - | - | - | ✅ | - | - | - |
AddToml() |
- | - | - | - | - | ✅ | - | - |
AddRedis() |
- | - | - | - | - | - | ✅ | - |
AddDatabase() |
- | - | - | - | - | - | - | ✅ |
| 多层级覆盖 | ||||||||
| 高层级覆盖低层级 | ✅ | ✅ | - | - | - | - | ✅ | ✅ |
说明:
-表示该配置源不支持此功能(如环境变量只读)或该功能只需测试一次
| 场景类别 | 测试文件 | 测试数量 |
|---|---|---|
| 基本读写 | JsonCfgTests, 各格式测试 | 47 |
| 类型转换 | JsonCfgTests | 15 |
| 编码检测 | EncodingDetectionTests | 14 |
| 并发安全 | ConcurrencyTests | 10 |
| 边界条件 | BoundaryConditionTests | 32 |
| 异常处理 | ExceptionHandlingTests | 20 |
| 动态重载 | DynamicReloadTests | 12 |
| 变更订阅 | ConfigChangesSubscriptionTests | 28 |
100% - 所有公开 API 均已覆盖测试
| 框架 | 测试数量 | 状态 | 测试日期 |
|---|---|---|---|
| .NET 6.0 | 175 | ✅ 全部通过 | 2025-12-24 |
| .NET 8.0 | 175 | ✅ 全部通过 | 2025-12-24 |
| .NET 9.0 | 175 | ✅ 全部通过 | 2025-12-24 |
测试环境:
| 操作 | .NET 9.0 | .NET 8.0 | .NET 6.0 | 说明 |
|---|---|---|---|---|
| Get (字符串) | 16 ns | 16 ns | 26 ns | 零内存分配 |
| Exists | 16 ns | 16 ns | 26 ns | 零内存分配 |
| Set | 19 ns | 19 ns | 26 ns | 零内存分配 |
| GetInt | 70 ns | 75 ns | 164 ns | 类型转换 |
结论:
| 格式 | .NET 9.0 | .NET 8.0 | .NET 6.0 | 内存 |
|---|---|---|---|---|
| Ini | 197 μs | 198 μs | 251 μs | 318 KB |
| Json | 252 μs | 257 μs | 267 μs | 380 KB |
| Xml | 633 μs | 527 μs | 571 μs | 1,160 KB |
| Yaml | 849 μs | 974 μs | 1,217 μs | 1,275 KB |
| Toml | 906 μs | 948 μs | 1,200 μs | 2,364 KB |
结论:
| 操作 | .NET 9.0 | .NET 8.0 | .NET 6.0 |
|---|---|---|---|
| 读相同键 | 2.9 μs | 2.9 μs | 5.7 μs |
| 读不同键 | 3.2 μs | 3.3 μs | 6.2 μs |
| Exists | 4.6 μs | 4.5 μs | 12.1 μs |
| 混合读写 | 11.7 μs | 16.2 μs | 22.2 μs |
| 写不同键 | 14.8 μs | 18.9 μs | 25.2 μs |
| 写相同键 | 38.0 μs | 42.0 μs | 43.8 μs |
结论:
| 场景 | .NET 9.0 | .NET 8.0 | .NET 6.0 |
|---|---|---|---|
| 热路径读取 (1000次) | 13.7 μs | 12.9 μs | 21.1 μs |
| 首次访问 | 15 ns | 15 ns | 23 ns |
| 后续访问 (预热后) | 1.4 μs | 1.5 μs | 2.4 μs |
| 缓存未命中 (1000次) | 13.6 μs | 12.7 μs | 22.2 μs |
结论:
| 类型 | .NET 9.0 | .NET 8.0 | .NET 6.0 | 内存 (.NET 9) |
|---|---|---|---|---|
| String | 18 ns | 19 ns | 25 ns | 0 B |
| Int | 88 ns | 74 ns | 143 ns | 64 B |
| Bool | 66 ns | 94 ns | 107 ns | 64 B |
| Double | 121 ns | 104 ns | 140 ns | 64 B |
| Guid | 80 ns | 115 ns | 161 ns | 72 B |
| DateTime | 135 ns | 203 ns | 209 ns | 64 B |
| Enum | 93 ns | 157 ns | 240 ns | 64 B |
结论:
| 场景 | 推荐格式 | 说明 |
|---|---|---|
| 高频读写 | Json / Ini | 单次操作 16-20 ns |
| 大配置文件 | Ini / Json | Ini 内存最省 |
| 人类可读性优先 | Yaml / Toml | 性能可接受 |
| 与现有系统集成 | Xml | 兼容性好 |
性能测试运行方法见 benchmarks/README.md
MIT License