Compare commits

..

7 Commits

Author SHA1 Message Date
7cea589294 test: 删除配置项示例 2025-01-21 19:23:57 +08:00
ad15422700 feat: 添加删除配置项的功能 2025-01-21 19:23:47 +08:00
6e3450fef2 docs: 更新使用方法说明 2025-01-21 19:15:49 +08:00
47e80bfebc refactor: 清理代码 2025-01-21 19:15:35 +08:00
17f78685fc feat: 添加 Get 方法的重载版本 2025-01-21 19:12:04 +08:00
bfe24d1e4b test: 更新配置测试用例 2025-01-21 19:02:09 +08:00
5cd01a6375 feat: 优化配置文件读写逻辑
- 修改配置数据初始化方式,提高代码可读性- 完善 Get 方法,增加默认值设置和类型转换逻辑- 重构 Set 方法,优化配置数据更新流程
- 更新解决方案设置
2025-01-21 19:01:55 +08:00
4 changed files with 111 additions and 11 deletions

View File

@@ -1,4 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACastHelpers_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6d2342c247c64eb7a9b3702e481e4443f83e00_003F54_003Ff2c78e92_003FCastHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExceptionDispatchInfo_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fbf9021a960b74107a7e141aa06bc9d8a0a53c929178c2fb95b1597be8af8dc_003FExceptionDispatchInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExceptionDispatchInfo_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fbf9021a960b74107a7e141aa06bc9d8a0a53c929178c2fb95b1597be8af8dc_003FExceptionDispatchInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFileInfo_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F2610c78ec589e1aacd82c4428835c427b838e8156a6f346f517d28ef9ffbb9a2_003FFileInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFileInfo_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F2610c78ec589e1aacd82c4428835c427b838e8156a6f346f517d28ef9ffbb9a2_003FFileInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFile_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6d2342c247c64eb7a9b3702e481e4443f83e00_003Fa1_003F11a17405_003FFile_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFile_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6d2342c247c64eb7a9b3702e481e4443f83e00_003Fa1_003F11a17405_003FFile_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJsonSerializerInternalReader_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7e62198beab24380bbac29171862d1d8adf10_003F90_003F0d01fe57_003FJsonSerializerInternalReader_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJsonSerializerInternalReader_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F29ea32a76b2a6b8eb246f247df6a6a86d887384b4c31db2a35effccdd86c24_003FJsonSerializerInternalReader_002Ecs_002Fz_003A2_002D1/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

View File

@@ -8,7 +8,7 @@ public class Config
private readonly FileInfo _configFile; private readonly FileInfo _configFile;
public readonly string ConfigFileName; public readonly string ConfigFileName;
public readonly string ConfigFilePath; public readonly string ConfigFilePath;
private Dictionary<string, object> _configData = null!; private Dictionary<string, object> _configData = new();
public Config(FileInfo configFile) public Config(FileInfo configFile)
{ {
@@ -39,6 +39,11 @@ public class Config
} }
} }
public T? Get<T>(string key)
{
return Get<T>(key, default);
}
public T? Get<T>(string key, T? defaultValue) public T? Get<T>(string key, T? defaultValue)
{ {
LoadConfigData(); LoadConfigData();
@@ -46,7 +51,12 @@ public class Config
var currentData = _configData; var currentData = _configData;
for (var i = 0; i < keys.Length - 1; i++) for (var i = 0; i < keys.Length - 1; i++)
{ {
if (!currentData.TryGetValue(keys[i], out var tValue)) return defaultValue; if (!currentData.TryGetValue(keys[i], out var tValue))
{
Set(key, defaultValue);
return defaultValue;
}
switch (tValue) switch (tValue)
{ {
case JObject jObject: case JObject jObject:
@@ -56,12 +66,14 @@ public class Config
currentData = nestedDict; currentData = nestedDict;
break; break;
default: default:
Set(key, defaultValue);
return defaultValue; return defaultValue;
} }
} }
if (currentData.TryGetValue(keys[^1], out var result) && result is T typedResult) return typedResult; if (currentData.TryGetValue(keys[^1], out var result) && result is T typedResult) return typedResult;
Set(key, defaultValue);
return defaultValue; return defaultValue;
} }
@@ -70,19 +82,53 @@ public class Config
LoadConfigData(); LoadConfigData();
var keys = key.Split('.'); var keys = key.Split('.');
var currentData = _configData; var currentData = _configData;
for (var i = 0; i < keys.Length - 1; i++) for (var i = 0; i < keys.Length - 1; i++)
{ {
if (!currentData.TryGetValue(keys[i], out var tValue) || var currentKey = keys[i];
tValue is not Dictionary<string, object> nestedDict)
if (!currentData.TryGetValue(currentKey, out var tValue))
{ {
nestedDict = new Dictionary<string, object>(); tValue = new Dictionary<string, object>();
currentData[keys[i]] = nestedDict; currentData[currentKey] = tValue;
} }
currentData = nestedDict; if (tValue is JObject jObject)
currentData[currentKey] =
jObject.ToObject<Dictionary<string, object>>() ?? new Dictionary<string, object>();
currentData = (Dictionary<string, object>)currentData[currentKey];
} }
currentData[keys[^1]] = (object?)value ?? string.Empty; var finalKey = keys[^1];
currentData[finalKey] = value!;
var json = JsonConvert.SerializeObject(_configData, Formatting.Indented);
File.WriteAllText(_configFile.FullName, json);
}
public void Delete(string key)
{
LoadConfigData();
var keys = key.Split('.');
var currentData = _configData;
for (var i = 0; i < keys.Length - 1; i++)
{
var currentKey = keys[i];
if (!currentData.TryGetValue(currentKey, out var value)) return;
if (value is JObject jObject)
currentData[currentKey] =
jObject.ToObject<Dictionary<string, object>>() ?? new Dictionary<string, object>();
currentData = (Dictionary<string, object>)currentData[currentKey];
}
var finalKey = keys[^1];
currentData.Remove(finalKey);
var json = JsonConvert.SerializeObject(_configData, Formatting.Indented); var json = JsonConvert.SerializeObject(_configData, Formatting.Indented);
File.WriteAllText(_configFile.FullName, json); File.WriteAllText(_configFile.FullName, json);
} }

View File

@@ -1,3 +1,49 @@
# JackCraft.Config # JackCraft.Config
一个自己觉得怎么好用怎么写的配置文件库 一个自己觉得怎么好用怎么写的配置文件库
## 使用方法
### 获取配置文件
> 配置文件不存在时会自动创建一个空 Json 文件,但是若配置文件不是 Json 标准格式将会在写入和读取键值时抛出异常
```csharp
// 标准示例: var config = new Config(new FileInfo(配置文件路径));
var config = new Config(new FileInfo("./config.json"));
```
### 读取键值
> 若键不存在则返回默认值,并且同时也会写入键值(若没有提供默认值则写入空)
```csharp
// 标准示例: var value = config.Get<T>(键, <可选>默认值);
// {
// "114514": "1919810"
// }
var value = config.Get("114514", "1919810");
var value = config.Get<string>("114514");
// {
// "abc": {
// "def": 1234
// }
// }
var value = config.Get("abc.def", 1234);
var value = config.Get<int>("abc.def");
```
### 写入键值
```csharp
// 标准示例: config.Set<T>(键, 值);
// {
// "114514": "1919810"
// }
config.Set("114514", "1919810");
// 其他类型与 Get<T> 同理...
```

View File

@@ -13,7 +13,12 @@ internal static class Program
Abc = 123 Abc = 123
}; };
var config = new Config(new FileInfo("./config.json")); var config = new Config(new FileInfo("./config.json"));
var t = config.Get("aaa.www.aaa.ccc", "1"); var a = config.Get("aaa.www.www", "555");
var b = config.Get("aaa.bbb", "1");
var c = config.Get("aaa.sss", "1");
var d = config.Get("bbb.sss", "1");
config.Delete("aaa.www");
} }
} }