diff --git a/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.Models.cs b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.Models.cs
index 7edbfdac..adbe74f7 100644
--- a/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.Models.cs
+++ b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.Models.cs
@@ -23,7 +23,9 @@ public sealed partial class CqrsHandlerRegistryGenerator
private readonly record struct ReflectedImplementationRegistrationSpec(
string HandlerInterfaceDisplayName,
- string HandlerInterfaceLogName);
+ string HandlerInterfaceLogName,
+ RequestInvokerRegistrationSpec? RequestInvokerRegistration,
+ StreamInvokerRegistrationSpec? StreamInvokerRegistration);
private readonly record struct OrderedRegistrationSpec(
string HandlerInterfaceLogName,
diff --git a/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.SourceEmission.cs b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.SourceEmission.cs
index ae539d23..7a449158 100644
--- a/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.SourceEmission.cs
+++ b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.SourceEmission.cs
@@ -73,7 +73,7 @@ public sealed partial class CqrsHandlerRegistryGenerator
}
///
- /// 从 direct handler 注册描述中提取 request invoker 发射计划。
+ /// 从可直接表达 handler 接口的注册描述中提取 request invoker 发射计划。
///
///
/// 指示当前 runtime 是否同时暴露 ICqrsRequestInvokerProvider 与
@@ -81,7 +81,8 @@ public sealed partial class CqrsHandlerRegistryGenerator
///
/// 已按稳定顺序整理完成的 handler 注册描述。
///
- /// 由 directRegistration.RequestInvokerRegistration 派生出的 集合。
+ /// 由 direct registration 或 reflected-implementation registration 上的
+ /// RequestInvokerRegistration 派生出的 集合。
/// methodIndex 按 与其 direct registration 的遍历顺序单调递增,
/// 因而只要上游排序稳定,生成的 invoker 方法名与描述符顺序就跨运行保持稳定。
///
@@ -111,13 +112,25 @@ public sealed partial class CqrsHandlerRegistryGenerator
directRegistration.HandlerInterfaceDisplayName,
methodIndex++));
}
+
+ foreach (var reflectedRegistration in registration.ReflectedImplementationRegistrations)
+ {
+ if (reflectedRegistration.RequestInvokerRegistration is not { } requestInvokerRegistration)
+ continue;
+
+ builder.Add(new RequestInvokerEmissionSpec(
+ requestInvokerRegistration.RequestTypeDisplayName,
+ requestInvokerRegistration.ResponseTypeDisplayName,
+ reflectedRegistration.HandlerInterfaceDisplayName,
+ methodIndex++));
+ }
}
return builder.ToImmutable();
}
///
- /// 从 direct handler 注册描述中提取 stream invoker 发射计划。
+ /// 从可直接表达 handler 接口的注册描述中提取 stream invoker 发射计划。
///
///
/// 指示当前 runtime 是否同时暴露 ICqrsStreamInvokerProvider 与
@@ -125,7 +138,8 @@ public sealed partial class CqrsHandlerRegistryGenerator
///
/// 已按稳定顺序整理完成的 handler 注册描述。
///
- /// 由 directRegistration.StreamInvokerRegistration 派生出的 集合。
+ /// 由 direct registration 或 reflected-implementation registration 上的
+ /// StreamInvokerRegistration 派生出的 集合。
/// methodIndex 按 与其 direct registration 的遍历顺序单调递增,
/// 因而只要上游排序稳定,生成的 invoker 方法名与描述符顺序就跨运行保持稳定。
///
@@ -151,6 +165,18 @@ public sealed partial class CqrsHandlerRegistryGenerator
directRegistration.HandlerInterfaceDisplayName,
methodIndex++));
}
+
+ foreach (var reflectedRegistration in registration.ReflectedImplementationRegistrations)
+ {
+ if (reflectedRegistration.StreamInvokerRegistration is not { } streamInvokerRegistration)
+ continue;
+
+ builder.Add(new StreamInvokerEmissionSpec(
+ streamInvokerRegistration.RequestTypeDisplayName,
+ streamInvokerRegistration.ResponseTypeDisplayName,
+ reflectedRegistration.HandlerInterfaceDisplayName,
+ methodIndex++));
+ }
}
return builder.ToImmutable();
diff --git a/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs
index 80a2c5a6..db547a04 100644
--- a/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs
+++ b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs
@@ -258,7 +258,13 @@ public sealed partial class CqrsHandlerRegistryGenerator : IIncrementalGenerator
{
reflectedImplementationRegistrations.Add(new ReflectedImplementationRegistrationSpec(
handlerInterface.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
- GetLogDisplayName(handlerInterface)));
+ GetLogDisplayName(handlerInterface),
+ TryCreateRequestInvokerRegistrationSpec(handlerInterface, out var requestInvokerRegistration)
+ ? requestInvokerRegistration
+ : null,
+ TryCreateStreamInvokerRegistrationSpec(handlerInterface, out var streamInvokerRegistration)
+ ? streamInvokerRegistration
+ : null));
return true;
}
diff --git a/ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md b/ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
index ef965277..4a130c1c 100644
--- a/ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
+++ b/ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md
@@ -7,7 +7,7 @@ CQRS 迁移与收敛。
## 当前恢复点
-- 恢复点编号:`CQRS-REWRITE-RP-068`
+- 恢复点编号:`CQRS-REWRITE-RP-069`
- 当前阶段:`Phase 8`
- 当前焦点:
- 已完成一轮 `CQRS vs Mediator` 只读评估归档,结论已沉淀到 `archive/todos/cqrs-vs-mediator-assessment-rp063.md`
@@ -60,6 +60,10 @@ CQRS 迁移与收敛。
- `GFramework.SourceGenerators.Tests` 已补充 generator 回归,锁定当 runtime 暴露新契约时,generated registry 会额外发射 stream invoker provider 成员与 invoker 方法
- `GFramework.Cqrs/README.md`、`GFramework.Cqrs.SourceGenerators/README.md`、`docs/zh-CN/core/cqrs.md` 与
`docs/zh-CN/source-generators/cqrs-handler-registry-generator.md` 现已同步说明 generated stream invoker 的接线与回退边界
+ - 已完成一轮 generated invoker 发射范围补强:
+ - `CqrsHandlerRegistryGenerator` 现会把 generated request / stream invoker 的发射范围,从“仅 direct registration”扩大到“实现类型隐藏、但 handler interface 仍可直接表达”的 reflected-implementation registration
+ - 当前扩展仍刻意避开 `PreciseReflectedRegistrationSpec`,不把隐藏 request/response 类型误拉进 provider 发射,继续保持生成源码可编译边界
+ - `GFramework.SourceGenerators.Tests` 已新增两条 hidden-implementation 回归,锁定 request / stream provider 在该场景下都会继续发射 descriptor 与静态 invoker 方法
- 已将 mixed fallback 场景进一步收敛:当 runtime 允许同一程序集声明多个 `CqrsReflectionFallbackAttribute` 实例时,generator 现会把可直接引用的 fallback handlers 与仅能按名称恢复的 fallback handlers 拆分发射
- `CqrsReflectionFallbackAttribute` 现允许多实例,以承载 `Type[]` 与字符串 fallback 元数据的组合输出
- 已将 generator 的程序集级 fallback 元数据进一步收敛:当全部 fallback handlers 都可直接引用且 runtime 暴露 `params Type[]` 合同时,生成器现优先发射 `typeof(...)` 形式的 fallback 元数据
@@ -261,6 +265,9 @@ CQRS 迁移与收敛。
- `GIT_DIR=/mnt/f/gewuyou/System/Documents/WorkSpace/GameDev/GFramework/.git/worktrees/GFramework-cqrs GIT_WORK_TREE=/mnt/f/gewuyou/System/Documents/WorkSpace/GameDev/GFramework-WorkTree/GFramework-cqrs bash scripts/validate-csharp-naming.sh`
- 结果:通过
- 备注:`1059` 个 tracked C# 文件命名校验全部通过;本轮新增 stream invoker 类型与测试命名未引入回归
+- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Request_Invoker_Provider_Metadata_For_Hidden_Implementation_With_Visible_Interface|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Stream_Invoker_Provider_Metadata_For_Hidden_Implementation_With_Visible_Interface|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Request_Invoker_Provider_Metadata_When_Runtime_Contract_Is_Available|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Stream_Invoker_Provider_Metadata_When_Runtime_Contract_Is_Available"`
+ - 结果:通过
+ - 备注:`4/4` passed;确认 hidden implementation + visible interface 场景也会继续发射 request / stream invoker provider 元数据
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release`
- 结果:通过
- 备注:`0 warning / 0 error`;确认 `CqrsRuntimeModule` 接线变更未引入 `GFramework.Core` 模块构建问题
diff --git a/ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md b/ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
index 51e5951b..9a631f5f 100644
--- a/ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
+++ b/ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md
@@ -58,6 +58,34 @@
2. 优先候选仍是 notification 路径是否值得引入同类 generated invoker seam,或继续补强 request / stream provider 的公开 API 入口与诊断语义
3. 下一批落地前先提交当前 stream provider 批次,避免未提交改动持续堆叠
+### 阶段:generated invoker reflected-implementation 发射范围补强(CQRS-REWRITE-RP-069)
+
+- 在 `RP-068` 提交后,重新复算 branch diff,相对 `origin/main` 升至 `20 files / 1015 changed lines`,仍明显低于 `gframework-batch-boot 50` 的 stop condition,因此继续下一批
+- 本轮目标只收敛 source generator,不扩散到 runtime 或公开文档:把 generated request / stream invoker 的发射范围从“仅 direct registration”扩大到“实现类型隐藏、但 handler interface 可直接表达”的 reflected-implementation registration
+- 接受只读 subagent 结论后确认:
+ - 现有分类阶段已经为 reflected-implementation registration 保留了 request / stream invoker registration 元数据
+ - 真正缺口只在 `CreateRequestInvokerEmissions(...)` 与 `CreateStreamInvokerEmissions(...)` 仍只遍历 `DirectRegistrations`
+ - `PreciseReflectedRegistrationSpec` 继续排除在 provider 发射范围外,避免隐藏 request/response 类型导致生成源码不可编译
+- 主线程已完成:
+ - `ReflectedImplementationRegistrationSpec` 显式承载 request / stream invoker registration 元数据
+ - `CreateRequestInvokerEmissions(...)` 与 `CreateStreamInvokerEmissions(...)` 现会同时消费 reflected-implementation registration
+ - `GFramework.SourceGenerators.Tests` 已新增 hidden-implementation + visible-interface 两条 provider 回归
+- 本轮不改 runtime:dispatcher / registrar 对 generated provider 的消费语义保持不变,变化只在 generator 愿意发射更多可安全静态表达的 descriptor
+
+### 验证(RP-069)
+
+- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release`
+ - 结果:通过,`0 warning / 0 error`
+- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Generates_Direct_Interface_Registrations_For_Hidden_Implementation_When_Handler_Interface_Is_Public|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Request_Invoker_Provider_Metadata_When_Runtime_Contract_Is_Available|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Stream_Invoker_Provider_Metadata_When_Runtime_Contract_Is_Available"`
+ - 结果:通过,`3/3` passed
+- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Request_Invoker_Provider_Metadata_For_Hidden_Implementation_With_Visible_Interface|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Stream_Invoker_Provider_Metadata_For_Hidden_Implementation_With_Visible_Interface|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Request_Invoker_Provider_Metadata_When_Runtime_Contract_Is_Available|FullyQualifiedName~CqrsHandlerRegistryGeneratorTests.Emits_Stream_Invoker_Provider_Metadata_When_Runtime_Contract_Is_Available"`
+ - 结果:通过,`4/4` passed
+
+### 当前下一步(RP-069)
+
+1. 提交当前 generator-only 批次,继续保持每个低风险切片可独立回滚与审查
+2. 继续评估下一个能明显降低反射占比、但不需要同时改动 runtime 语义的切片
+
### 阶段:generated request invoker provider 最小落地(CQRS-REWRITE-RP-067)
- 继续按 `gframework-batch-boot 50` 执行,基线仍为本地现有 `origin/main`