From 7da35c00b268aa81234c9b65f782bd8ea6da42dd Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Mon, 6 Apr 2026 07:53:46 +0800
Subject: [PATCH] =?UTF-8?q?feat(config):=20=E6=B7=BB=E5=8A=A0=E5=9F=BA?=
=?UTF-8?q?=E4=BA=8E=E6=96=87=E4=BB=B6=E7=9B=AE=E5=BD=95=E7=9A=84YAML?=
=?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8A=A0=E8=BD=BD=E5=99=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 实现YamlConfigLoader类,支持从文件目录加载YAML配置
- 提供RegisterTable方法注册配置表定义,支持schema校验
- 添加LoadAsync异步加载功能,支持批量加载配置表
- 实现EnableHotReload方法,支持开发期配置热重载
- 添加跨表引用校验功能,确保配置依赖关系正确性
- 支持YAML文件和YML文件格式,自动识别文件扩展名
- 提供配置表主键提取器和比较器自定义功能
- 实现文件变更监听和防抖机制,避免频繁重载
- 支持配置目录和schema文件路径的灵活配置
- 提供详细的加载异常信息和诊断支持
---
.../Config/YamlConfigLoaderTests.cs | 20 +++++++++++
GFramework.Game/Config/YamlConfigLoader.cs | 13 ++++++++
.../Config/SchemaConfigGeneratorTests.cs | 33 +++++++++++--------
3 files changed, 52 insertions(+), 14 deletions(-)
diff --git a/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs b/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs
index f2045ad3..86f01098 100644
--- a/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs
+++ b/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs
@@ -1133,6 +1133,26 @@ public class YamlConfigLoaderTests
}
}
+ ///
+ /// 验证热重载会在启动前拒绝负的防抖延迟,避免后台延迟任务才暴露参数错误。
+ ///
+ [Test]
+ public void EnableHotReload_Should_Throw_When_Debounce_Delay_Is_Negative()
+ {
+ var loader = new YamlConfigLoader(_rootPath);
+ var registry = new ConfigRegistry();
+
+ var exception = Assert.Throws(() =>
+ loader.EnableHotReload(
+ registry,
+ new YamlConfigHotReloadOptions
+ {
+ DebounceDelay = TimeSpan.FromMilliseconds(-1)
+ }));
+
+ Assert.That(exception!.ParamName, Is.EqualTo("options"));
+ }
+
///
/// 验证热重载失败时会保留旧表状态,并通过失败回调暴露诊断信息。
///
diff --git a/GFramework.Game/Config/YamlConfigLoader.cs b/GFramework.Game/Config/YamlConfigLoader.cs
index 491505fd..012caa32 100644
--- a/GFramework.Game/Config/YamlConfigLoader.cs
+++ b/GFramework.Game/Config/YamlConfigLoader.cs
@@ -97,6 +97,9 @@ public sealed class YamlConfigLoader : IConfigLoader
/// 防抖延迟;为空时默认使用 200 毫秒。
/// 用于停止热重载监听的注销句柄。
/// 当 为空时抛出。
+ ///
+ /// 当显式提供的 小于 时抛出。
+ ///
public IUnRegister EnableHotReload(
IConfigRegistry registry,
Action? onTableReloaded = null,
@@ -122,12 +125,22 @@ public sealed class YamlConfigLoader : IConfigLoader
/// 热重载配置选项;为空时使用默认选项。
/// 用于停止热重载监听的注销句柄。
/// 当 为空时抛出。
+ ///
+ /// 当 的 小于
+ /// 时抛出。
+ ///
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,
diff --git a/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
index 9c777f4c..07b3b81c 100644
--- a/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
+++ b/GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs
@@ -95,8 +95,13 @@ public class SchemaConfigGeneratorTests
///
/// 验证 schema 字段名无法映射为合法 C# 标识符时会直接给出诊断,而不是生成不可编译代码。
///
- [Test]
- public void Run_Should_Report_Diagnostic_When_Schema_Key_Maps_To_Invalid_CSharp_Identifier()
+ /// 会映射为非法 C# 标识符的 schema key。
+ /// 当前命名规范化逻辑生成出的非法标识符。
+ [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));
});
}