mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-08 09:34:30 +08:00
feat(config): 添加基于文件目录的YAML配置加载器
- 实现YamlConfigLoader类,支持从文件目录加载YAML配置 - 提供RegisterTable方法注册配置表定义,支持schema校验 - 添加LoadAsync异步加载功能,支持批量加载配置表 - 实现EnableHotReload方法,支持开发期配置热重载 - 添加跨表引用校验功能,确保配置依赖关系正确性 - 支持YAML文件和YML文件格式,自动识别文件扩展名 - 提供配置表主键提取器和比较器自定义功能 - 实现文件变更监听和防抖机制,避免频繁重载 - 支持配置目录和schema文件路径的灵活配置 - 提供详细的加载异常信息和诊断支持
This commit is contained in:
parent
a416e093ee
commit
7da35c00b2
@ -1133,6 +1133,26 @@ public class YamlConfigLoaderTests
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证热重载会在启动前拒绝负的防抖延迟,避免后台延迟任务才暴露参数错误。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void EnableHotReload_Should_Throw_When_Debounce_Delay_Is_Negative()
|
||||
{
|
||||
var loader = new YamlConfigLoader(_rootPath);
|
||||
var registry = new ConfigRegistry();
|
||||
|
||||
var exception = Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
loader.EnableHotReload(
|
||||
registry,
|
||||
new YamlConfigHotReloadOptions
|
||||
{
|
||||
DebounceDelay = TimeSpan.FromMilliseconds(-1)
|
||||
}));
|
||||
|
||||
Assert.That(exception!.ParamName, Is.EqualTo("options"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证热重载失败时会保留旧表状态,并通过失败回调暴露诊断信息。
|
||||
/// </summary>
|
||||
|
||||
@ -97,6 +97,9 @@ public sealed class YamlConfigLoader : IConfigLoader
|
||||
/// <param name="debounceDelay">防抖延迟;为空时默认使用 200 毫秒。</param>
|
||||
/// <returns>用于停止热重载监听的注销句柄。</returns>
|
||||
/// <exception cref="ArgumentNullException">当 <paramref name="registry" /> 为空时抛出。</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// 当显式提供的 <paramref name="debounceDelay" /> 小于 <see cref="TimeSpan.Zero" /> 时抛出。
|
||||
/// </exception>
|
||||
public IUnRegister EnableHotReload(
|
||||
IConfigRegistry registry,
|
||||
Action<string>? onTableReloaded = null,
|
||||
@ -122,12 +125,22 @@ public sealed class YamlConfigLoader : IConfigLoader
|
||||
/// <param name="options">热重载配置选项;为空时使用默认选项。</param>
|
||||
/// <returns>用于停止热重载监听的注销句柄。</returns>
|
||||
/// <exception cref="ArgumentNullException">当 <paramref name="registry" /> 为空时抛出。</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// 当 <paramref name="options" /> 的 <see cref="YamlConfigHotReloadOptions.DebounceDelay" /> 小于
|
||||
/// <see cref="TimeSpan.Zero" /> 时抛出。
|
||||
/// </exception>
|
||||
public IUnRegister EnableHotReload(
|
||||
IConfigRegistry registry,
|
||||
YamlConfigHotReloadOptions? options)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(registry);
|
||||
options ??= new YamlConfigHotReloadOptions();
|
||||
if (options.DebounceDelay < TimeSpan.Zero)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(options),
|
||||
"DebounceDelay must be greater than or equal to zero.");
|
||||
}
|
||||
|
||||
return new HotReloadSession(
|
||||
_rootPath,
|
||||
|
||||
@ -95,8 +95,13 @@ public class SchemaConfigGeneratorTests
|
||||
/// <summary>
|
||||
/// 验证 schema 字段名无法映射为合法 C# 标识符时会直接给出诊断,而不是生成不可编译代码。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Run_Should_Report_Diagnostic_When_Schema_Key_Maps_To_Invalid_CSharp_Identifier()
|
||||
/// <param name="schemaKey">会映射为非法 C# 标识符的 schema key。</param>
|
||||
/// <param name="generatedIdentifier">当前命名规范化逻辑生成出的非法标识符。</param>
|
||||
[TestCase("drop$item", "Drop$item")]
|
||||
[TestCase("1-phase", "1Phase")]
|
||||
public void Run_Should_Report_Diagnostic_When_Schema_Key_Maps_To_Invalid_CSharp_Identifier(
|
||||
string schemaKey,
|
||||
string generatedIdentifier)
|
||||
{
|
||||
const string source = """
|
||||
namespace TestApp
|
||||
@ -107,16 +112,16 @@ public class SchemaConfigGeneratorTests
|
||||
}
|
||||
""";
|
||||
|
||||
const string schema = """
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "drop$item"],
|
||||
"properties": {
|
||||
"id": { "type": "integer" },
|
||||
"drop$item": { "type": "string" }
|
||||
}
|
||||
}
|
||||
""";
|
||||
var schema = $$"""
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "{{schemaKey}}"],
|
||||
"properties": {
|
||||
"id": { "type": "integer" },
|
||||
"{{schemaKey}}": { "type": "string" }
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
var result = SchemaGeneratorTestDriver.Run(
|
||||
source,
|
||||
@ -128,8 +133,8 @@ public class SchemaConfigGeneratorTests
|
||||
{
|
||||
Assert.That(diagnostic.Id, Is.EqualTo("GF_ConfigSchema_006"));
|
||||
Assert.That(diagnostic.Severity, Is.EqualTo(DiagnosticSeverity.Error));
|
||||
Assert.That(diagnostic.GetMessage(), Does.Contain("drop$item"));
|
||||
Assert.That(diagnostic.GetMessage(), Does.Contain("Drop$item"));
|
||||
Assert.That(diagnostic.GetMessage(), Does.Contain(schemaKey));
|
||||
Assert.That(diagnostic.GetMessage(), Does.Contain(generatedIdentifier));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user