From 0cf4945e78afef4e78324670f7d3a79e7c7a0be0 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 16 Apr 2026 21:01:01 +0800 Subject: [PATCH] =?UTF-8?q?docs(config):=20=E6=B7=BB=E5=8A=A0=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E5=86=85=E5=AE=B9=E9=85=8D=E7=BD=AE=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 CQRS 架构模式详细文档,包括命令查询职责分离核心概念 - 添加命令、查询、处理器、请求分发器等基本用法示例 - 包含高级用法如通知、管道行为、流式处理等完整功能介绍 - 提供最佳实践指南和常见问题解决方案 - 添加游戏内容配置系统文档,涵盖 YAML 配置源文件和 JSON Schema 结构描述 - 包含推荐目录结构、Schema 示例和 YAML 示例配置 - 提供完整的接入模板,包括 csproj 配置、启动帮助器和运行时读取模板 - 添加 Godot 文本配置桥接、热重载和 Architecture 接入等高级功能说明 --- .../AutoRegisterModuleAttribute.cs | 2 +- .../Architectures/RegisterModelAttribute.cs | 2 +- .../Architectures/RegisterSystemAttribute.cs | 2 +- .../Architectures/RegisterUtilityAttribute.cs | 2 +- .../Bases/PriorityAttribute.cs | 2 +- .../Enums/GenerateEnumExtensionsAttribute.cs | 2 +- .../Logging/LogAttribute.cs | 2 +- .../Rule/ContextAwareAttribute.cs | 2 +- .../Rule/GetAllAttribute.cs | 2 +- .../Rule/GetModelAttribute.cs | 2 +- .../Rule/GetModelsAttribute.cs | 2 +- .../Rule/GetServiceAttribute.cs | 2 +- .../Rule/GetServicesAttribute.cs | 2 +- .../Rule/GetSystemAttribute.cs | 2 +- .../Rule/GetSystemsAttribute.cs | 16 +- .../Rule/GetUtilitiesAttribute.cs | 2 +- .../Rule/GetUtilityAttribute.cs | 2 +- .../Analyzers/ContextRegistrationAnalyzer.cs | 4 +- .../Analyzers/PriorityUsageAnalyzer.cs | 4 +- .../AutoRegisterModuleGenerator.cs | 6 +- .../Bases/PriorityGenerator.cs | 4 +- .../AutoRegisterModuleDiagnostics.cs | 2 +- .../Diagnostics/ContextAwareDiagnostic.cs | 2 +- .../Diagnostics/ContextGetDiagnostics.cs | 2 +- .../ContextRegistrationDiagnostics.cs | 2 +- .../Diagnostics/LoggerDiagnostic.cs | 2 +- .../Diagnostics/PriorityDiagnostic.cs | 2 +- .../Enums/EnumExtensionsGenerator.cs | 2 +- .../Logging/LoggerGenerator.cs | 4 +- .../Rule/ContextAwareGenerator.cs | 6 +- .../Rule/ContextGetGenerator.cs | 4 +- .../Cqrs/CqrsHandlerRegistryGenerator.cs | 27 +- .../Config/SchemaConfigGenerator.cs | 4 +- .../Diagnostics/ConfigSchemaDiagnostics.cs | 2 +- .../GFramework.Game.SourceGenerators.csproj | 1 + .../ContextRegistrationAnalyzerTests.cs | 249 +++++++++--------- .../AutoRegisterModuleGeneratorTests.cs | 69 ++--- .../Bases/PriorityGeneratorSnapshotTests.cs | 5 +- .../Config/SchemaGeneratorTestDriver.cs | 5 +- .../Cqrs/CqrsHandlerRegistryGeneratorTests.cs | 114 +++++--- .../EnumExtensionsGeneratorSnapshotTests.cs | 5 +- .../Logging/LoggerGeneratorSnapshotTests.cs | 5 +- .../ContextAwareGeneratorSnapshotTests.cs | 5 +- .../Rule/ContextGetGeneratorTests.cs | 2 +- GFramework.csproj | 17 +- README.md | 7 +- docs/zh-CN/core/cqrs.md | 2 + docs/zh-CN/game/config-system.md | 4 +- docs/zh-CN/getting-started/installation.md | 46 +++- docs/zh-CN/source-generators/index.md | 29 +- .../zh-CN/tutorials/basic/02-project-setup.md | 17 +- 51 files changed, 416 insertions(+), 293 deletions(-) diff --git a/GFramework.Core.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs index 04daaa46..08168ebf 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Architectures/AutoRegisterModuleAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Architectures; +namespace GFramework.Core.SourceGenerators.Abstractions.Architectures; /// /// 标记架构模块类型,Source Generator 会根据注册特性生成 Install 方法。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs index 6c47d8b1..5607fed7 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterModelAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Architectures; +namespace GFramework.Core.SourceGenerators.Abstractions.Architectures; /// /// 声明架构模块需要自动注册的模型类型。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs index 7119db2f..64f8e7ce 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterSystemAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Architectures; +namespace GFramework.Core.SourceGenerators.Abstractions.Architectures; /// /// 声明架构模块需要自动注册的系统类型。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs index 88e5d93c..4cde0498 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Architectures/RegisterUtilityAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Architectures; +namespace GFramework.Core.SourceGenerators.Abstractions.Architectures; /// /// 声明架构模块需要自动注册的工具类型。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs index 42459498..f2bfc9ab 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Bases/PriorityAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Bases; +namespace GFramework.Core.SourceGenerators.Abstractions.Bases; /// /// 标记类的优先级,自动生成 GFramework.Core.Abstractions.Bases.IPrioritized 接口实现。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs index c5136a88..a48c7b7f 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Enums/GenerateEnumExtensionsAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Enums; +namespace GFramework.Core.SourceGenerators.Abstractions.Enums; /// /// 标注在 enum 上,Source Generator 会为该 enum 生成扩展方法。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs index 0cddf94c..6ba80e27 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Logging/LogAttribute.cs @@ -1,5 +1,5 @@ #nullable enable -namespace GFramework.SourceGenerators.Abstractions.Logging; +namespace GFramework.Core.SourceGenerators.Abstractions.Logging; /// /// 标注在类上,Source Generator 会为该类自动生成一个日志记录器字段。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs index 7cb75238..6827cc30 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/ContextAwareAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记该类需要自动实现 IContextAware diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs index cd310da6..203a4ac7 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetAllAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记类需要自动推断并注入上下文相关字段。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs index b97d395f..59c8b44a 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入单个模型实例。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs index a6173a25..9bd9168e 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetModelsAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入模型集合。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs index 46c23320..fe652d17 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServiceAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入单个服务实例。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs index 5341d6a3..c81fcf2d 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetServicesAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入服务集合。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs index 072cd112..9bfc7b70 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入单个系统实例。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs index da214089..4b05b051 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetSystemsAttribute.cs @@ -1,8 +1,22 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入系统集合。 /// +/// +/// Source Generator 会为标记字段生成从当前架构上下文收集系统实例的注入代码,用于避免在组件内部重复书写 +/// GetSystems() 一类的样板访问逻辑。 +/// 被标记字段应声明为可承载多个系统实例的类型,例如 IEnumerable<ISystem> 或兼容集合接口。 +/// +/// +/// +/// public partial class CombatPanel : IContextAware +/// { +/// [GetSystems] +/// private IEnumerable<ISystem> _systems = Array.Empty<ISystem>(); +/// } +/// +/// [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class GetSystemsAttribute : Attribute { diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs index afeb63ee..5f9c65d6 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilitiesAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入工具集合。 diff --git a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs index 99059a96..3b934a67 100644 --- a/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs +++ b/GFramework.Core.SourceGenerators.Abstractions/Rule/GetUtilityAttribute.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Abstractions.Rule; +namespace GFramework.Core.SourceGenerators.Abstractions.Rule; /// /// 标记字段需要自动注入单个工具实例。 diff --git a/GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs b/GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs index dcd25ca8..57c49d08 100644 --- a/GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs +++ b/GFramework.Core.SourceGenerators/Analyzers/ContextRegistrationAnalyzer.cs @@ -1,9 +1,9 @@ +using GFramework.Core.SourceGenerators.Diagnostics; using GFramework.SourceGenerators.Common.Constants; -using GFramework.SourceGenerators.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; -namespace GFramework.SourceGenerators.Analyzers; +namespace GFramework.Core.SourceGenerators.Analyzers; /// /// 分析 Context Get 使用点是否能在所属架构中找到静态可见的 Model、System、Utility 注册。 diff --git a/GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs b/GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs index b58871a1..520448a6 100644 --- a/GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs +++ b/GFramework.Core.SourceGenerators/Analyzers/PriorityUsageAnalyzer.cs @@ -1,8 +1,8 @@ -using GFramework.SourceGenerators.Diagnostics; +using GFramework.Core.SourceGenerators.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; -namespace GFramework.SourceGenerators.Analyzers; +namespace GFramework.Core.SourceGenerators.Analyzers; /// /// 优先级使用分析器,检测应该使用 GetAllByPriority 而非 GetAll 的场景 diff --git a/GFramework.Core.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs b/GFramework.Core.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs index 0385d221..93771bc1 100644 --- a/GFramework.Core.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs +++ b/GFramework.Core.SourceGenerators/Architectures/AutoRegisterModuleGenerator.cs @@ -1,10 +1,10 @@ -using GFramework.SourceGenerators.Abstractions.Architectures; +using GFramework.Core.SourceGenerators.Abstractions.Architectures; +using GFramework.Core.SourceGenerators.Diagnostics; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Extensions; -using GFramework.SourceGenerators.Diagnostics; -namespace GFramework.SourceGenerators.Architectures; +namespace GFramework.Core.SourceGenerators.Architectures; /// /// 为标记了 的模块生成固定顺序的组件注册代码。 diff --git a/GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs b/GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs index b0331900..ee534f8a 100644 --- a/GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs +++ b/GFramework.Core.SourceGenerators/Bases/PriorityGenerator.cs @@ -1,8 +1,8 @@ +using GFramework.Core.SourceGenerators.Diagnostics; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Generator; -using GFramework.SourceGenerators.Diagnostics; -namespace GFramework.SourceGenerators.Bases; +namespace GFramework.Core.SourceGenerators.Bases; /// /// Priority 特性生成器,为标记了 [Priority] 的类自动生成 IPrioritized 接口实现 diff --git a/GFramework.Core.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs b/GFramework.Core.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs index 83b9566f..eb3323aa 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/AutoRegisterModuleDiagnostics.cs @@ -1,6 +1,6 @@ using GFramework.SourceGenerators.Common.Constants; -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; internal static class AutoRegisterModuleDiagnostics { diff --git a/GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs b/GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs index 70b06fc8..e84e1853 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/ContextAwareDiagnostic.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; /// /// 提供与上下文感知相关的诊断规则定义 diff --git a/GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs b/GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs index dd9534d4..be2e69e6 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs @@ -1,6 +1,6 @@ using GFramework.SourceGenerators.Common.Constants; -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; /// /// 提供 Context Get 注入生成器相关诊断。 diff --git a/GFramework.Core.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs b/GFramework.Core.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs index 7643c812..a6d9ba13 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/ContextRegistrationDiagnostics.cs @@ -1,6 +1,6 @@ using GFramework.SourceGenerators.Common.Constants; -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; /// /// 提供 Context Get 注册可见性分析相关诊断。 diff --git a/GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs b/GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs index 0ff2bf90..14238e16 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/LoggerDiagnostic.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; /// /// 提供诊断描述符的静态类,用于GFramework日志生成器的编译时检查 diff --git a/GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs b/GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs index 86030071..169143e3 100644 --- a/GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs +++ b/GFramework.Core.SourceGenerators/Diagnostics/PriorityDiagnostic.cs @@ -1,4 +1,4 @@ -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Core.SourceGenerators.Diagnostics; /// /// Priority 特性相关的诊断信息 diff --git a/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs b/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs index b04a3640..493c10e1 100644 --- a/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs +++ b/GFramework.Core.SourceGenerators/Enums/EnumExtensionsGenerator.cs @@ -2,7 +2,7 @@ using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Generator; -namespace GFramework.SourceGenerators.Enums; +namespace GFramework.Core.SourceGenerators.Enums; /// /// 枚举扩展方法生成器,用于自动生成枚举相关的扩展方法 diff --git a/GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs b/GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs index e861f0c3..2be4a1d4 100644 --- a/GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs +++ b/GFramework.Core.SourceGenerators/Logging/LoggerGenerator.cs @@ -1,9 +1,9 @@ -using GFramework.SourceGenerators.Abstractions.Logging; +using GFramework.Core.SourceGenerators.Abstractions.Logging; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Extensions; using GFramework.SourceGenerators.Common.Generator; -namespace GFramework.SourceGenerators.Logging; +namespace GFramework.Core.SourceGenerators.Logging; /// /// 日志生成器,用于为标记了LogAttribute的类自动生成日志字段 diff --git a/GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs b/GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs index 68c2ad45..9bdeb3f9 100644 --- a/GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs +++ b/GFramework.Core.SourceGenerators/Rule/ContextAwareGenerator.cs @@ -1,9 +1,9 @@ -using GFramework.SourceGenerators.Common.Constants; +using GFramework.Core.SourceGenerators.Diagnostics; +using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Generator; -using GFramework.SourceGenerators.Diagnostics; -namespace GFramework.SourceGenerators.Rule; +namespace GFramework.Core.SourceGenerators.Rule; /// /// 上下文感知生成器,用于为标记了ContextAware特性的类自动生成IContextAware接口实现 diff --git a/GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs b/GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs index c3915b00..f0b4aeba 100644 --- a/GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs +++ b/GFramework.Core.SourceGenerators/Rule/ContextGetGenerator.cs @@ -1,10 +1,10 @@ +using GFramework.Core.SourceGenerators.Diagnostics; using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Extensions; using GFramework.SourceGenerators.Common.Info; -using GFramework.SourceGenerators.Diagnostics; -namespace GFramework.SourceGenerators.Rule; +namespace GFramework.Core.SourceGenerators.Rule; /// /// 为上下文感知类生成 Core 上下文 Get 注入方法。 diff --git a/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs index 74e1daeb..ba63ea11 100644 --- a/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs +++ b/GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs @@ -1,6 +1,6 @@ using GFramework.SourceGenerators.Common.Constants; -namespace GFramework.SourceGenerators.Cqrs; +namespace GFramework.Cqrs.SourceGenerators.Cqrs; /// /// 为当前编译程序集生成 CQRS 处理器注册器,以减少运行时的程序集反射扫描成本。 @@ -347,7 +347,7 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator } runtimeTypeReference = RuntimeTypeReferenceSpec.FromExternalReflectionLookup( - namedType.ContainingAssembly.Identity.Name, + namedType.ContainingAssembly.Identity.ToString(), GetReflectionTypeMetadataName(namedType)); return true; } @@ -396,7 +396,7 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator } genericTypeDefinitionReference = RuntimeTypeReferenceSpec.FromExternalReflectionLookup( - genericTypeDefinition.ContainingAssembly.Identity.Name, + genericTypeDefinition.ContainingAssembly.Identity.ToString(), GetReflectionTypeMetadataName(genericTypeDefinition)); return true; } @@ -951,28 +951,39 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator if (includeExternalAssemblyTypeLookupHelpers) { builder.AppendLine( - " private static global::System.Type? ResolveReferencedAssemblyType(string assemblyName, string typeMetadataName)"); + " private static global::System.Type? ResolveReferencedAssemblyType(string assemblyIdentity, string typeMetadataName)"); builder.AppendLine(" {"); - builder.AppendLine(" var assembly = ResolveReferencedAssembly(assemblyName);"); + builder.AppendLine(" var assembly = ResolveReferencedAssembly(assemblyIdentity);"); builder.AppendLine( " return assembly?.GetType(typeMetadataName, throwOnError: false, ignoreCase: false);"); builder.AppendLine(" }"); builder.AppendLine(); builder.AppendLine( - " private static global::System.Reflection.Assembly? ResolveReferencedAssembly(string assemblyName)"); + " private static global::System.Reflection.Assembly? ResolveReferencedAssembly(string assemblyIdentity)"); builder.AppendLine(" {"); + builder.AppendLine(" global::System.Reflection.AssemblyName targetAssemblyName;"); + builder.AppendLine(" try"); + builder.AppendLine(" {"); + builder.AppendLine( + " targetAssemblyName = new global::System.Reflection.AssemblyName(assemblyIdentity);"); + builder.AppendLine(" }"); + builder.AppendLine(" catch"); + builder.AppendLine(" {"); + builder.AppendLine(" return null;"); + builder.AppendLine(" }"); + builder.AppendLine(); builder.AppendLine( " foreach (var assembly in global::System.AppDomain.CurrentDomain.GetAssemblies())"); builder.AppendLine(" {"); builder.AppendLine( - " if (global::System.StringComparer.Ordinal.Equals(assembly.GetName().Name, assemblyName))"); + " if (global::System.Reflection.AssemblyName.ReferenceMatchesDefinition(targetAssemblyName, assembly.GetName()))"); builder.AppendLine(" return assembly;"); builder.AppendLine(" }"); builder.AppendLine(); builder.AppendLine(" try"); builder.AppendLine(" {"); builder.AppendLine( - " return global::System.Reflection.Assembly.Load(new global::System.Reflection.AssemblyName(assemblyName));"); + " return global::System.Reflection.Assembly.Load(targetAssemblyName);"); builder.AppendLine(" }"); builder.AppendLine(" catch"); builder.AppendLine(" {"); diff --git a/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs b/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs index 8eafa13e..aca981c8 100644 --- a/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs +++ b/GFramework.Game.SourceGenerators/Config/SchemaConfigGenerator.cs @@ -1,6 +1,6 @@ -using GFramework.SourceGenerators.Diagnostics; +using GFramework.Game.SourceGenerators.Diagnostics; -namespace GFramework.SourceGenerators.Config; +namespace GFramework.Game.SourceGenerators.Config; /// /// 根据 AdditionalFiles 中的 JSON schema 生成配置类型和配置表包装。 diff --git a/GFramework.Game.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs b/GFramework.Game.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs index 115ecea2..04d1c02e 100644 --- a/GFramework.Game.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs +++ b/GFramework.Game.SourceGenerators/Diagnostics/ConfigSchemaDiagnostics.cs @@ -1,6 +1,6 @@ using GFramework.SourceGenerators.Common.Constants; -namespace GFramework.SourceGenerators.Diagnostics; +namespace GFramework.Game.SourceGenerators.Diagnostics; /// /// 提供配置 schema 代码生成相关诊断。 diff --git a/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj b/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj index e7cc0ae6..1c0a9bd1 100644 --- a/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj +++ b/GFramework.Game.SourceGenerators/GFramework.Game.SourceGenerators.csproj @@ -7,6 +7,7 @@ false latest enable + true true Generated true diff --git a/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs b/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs index 781a77bc..abcb4ccf 100644 --- a/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs +++ b/GFramework.SourceGenerators.Tests/Analyzers/ContextRegistrationAnalyzerTests.cs @@ -1,4 +1,4 @@ -using GFramework.SourceGenerators.Analyzers; +using GFramework.Core.SourceGenerators.Analyzers; using GFramework.SourceGenerators.Tests.Core; namespace GFramework.SourceGenerators.Tests.Analyzers; @@ -9,128 +9,128 @@ namespace GFramework.SourceGenerators.Tests.Analyzers; public sealed class ContextRegistrationAnalyzerTests { private const string TestPreamble = """ - using System; - using System.Collections.Generic; - - namespace GFramework.Core.Abstractions.Rule - { - public interface IContextAware { } - } - - namespace GFramework.Core.Abstractions.Model - { - public interface IModel : GFramework.Core.Abstractions.Rule.IContextAware { } - } - - namespace GFramework.Core.Abstractions.Systems - { - public interface ISystem : GFramework.Core.Abstractions.Rule.IContextAware { } - } - - namespace GFramework.Core.Abstractions.Utility - { - public interface IUtility : GFramework.Core.Abstractions.Rule.IContextAware { } - } - - namespace GFramework.Core.Abstractions.Architectures - { - public interface IArchitecture - { - T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel; - void RegisterModel(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Model.IModel; - T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem; - void RegisterSystem(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Systems.ISystem; - T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility; - void RegisterUtility(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Utility.IUtility; - IArchitectureModule InstallModule(IArchitectureModule module); - } - - public interface IArchitectureModule - { - void Install(IArchitecture architecture); - } - - public interface IArchitectureContext - { - TModel GetModel() where TModel : class, GFramework.Core.Abstractions.Model.IModel; - IReadOnlyList GetModels() where TModel : class, GFramework.Core.Abstractions.Model.IModel; - TSystem GetSystem() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem; - IReadOnlyList GetSystems() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem; - TUtility GetUtility() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility; - IReadOnlyList GetUtilities() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility; - } - } - - namespace GFramework.Core.Architectures - { - public abstract class Architecture : GFramework.Core.Abstractions.Architectures.IArchitecture - { - protected abstract void OnInitialize(); - - public virtual T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel => model; - - public virtual void RegisterModel(Action onCreated = null) - where T : class, GFramework.Core.Abstractions.Model.IModel - { - } - - public virtual T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem => system; - - public virtual void RegisterSystem(Action onCreated = null) - where T : class, GFramework.Core.Abstractions.Systems.ISystem - { - } - - public virtual T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility => utility; - - public virtual void RegisterUtility(Action onCreated = null) - where T : class, GFramework.Core.Abstractions.Utility.IUtility - { - } - - public virtual GFramework.Core.Abstractions.Architectures.IArchitectureModule InstallModule( - GFramework.Core.Abstractions.Architectures.IArchitectureModule module) - { - module.Install(this); - return module; - } - } - } - - namespace GFramework.Core.Extensions - { - public static class ContextAwareServiceExtensions - { - public static TModel GetModel(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException(); - - public static IReadOnlyList GetModels(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException(); - - public static TSystem GetSystem(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException(); - - public static IReadOnlyList GetSystems(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException(); - - public static TUtility GetUtility(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException(); - - public static IReadOnlyList GetUtilities(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) - where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException(); - } - } - - namespace GFramework.SourceGenerators.Abstractions.Rule - { - public sealed class GetModelAttribute : Attribute { } - public sealed class GetModelsAttribute : Attribute { } - public sealed class GetSystemAttribute : Attribute { } - public sealed class GetSystemsAttribute : Attribute { } - public sealed class GetUtilityAttribute : Attribute { } - public sealed class GetUtilitiesAttribute : Attribute { } - } - """; + using System; + using System.Collections.Generic; + + namespace GFramework.Core.Abstractions.Rule + { + public interface IContextAware { } + } + + namespace GFramework.Core.Abstractions.Model + { + public interface IModel : GFramework.Core.Abstractions.Rule.IContextAware { } + } + + namespace GFramework.Core.Abstractions.Systems + { + public interface ISystem : GFramework.Core.Abstractions.Rule.IContextAware { } + } + + namespace GFramework.Core.Abstractions.Utility + { + public interface IUtility : GFramework.Core.Abstractions.Rule.IContextAware { } + } + + namespace GFramework.Core.Abstractions.Architectures + { + public interface IArchitecture + { + T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel; + void RegisterModel(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Model.IModel; + T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem; + void RegisterSystem(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Systems.ISystem; + T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility; + void RegisterUtility(Action onCreated = null) where T : class, GFramework.Core.Abstractions.Utility.IUtility; + IArchitectureModule InstallModule(IArchitectureModule module); + } + + public interface IArchitectureModule + { + void Install(IArchitecture architecture); + } + + public interface IArchitectureContext + { + TModel GetModel() where TModel : class, GFramework.Core.Abstractions.Model.IModel; + IReadOnlyList GetModels() where TModel : class, GFramework.Core.Abstractions.Model.IModel; + TSystem GetSystem() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem; + IReadOnlyList GetSystems() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem; + TUtility GetUtility() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility; + IReadOnlyList GetUtilities() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility; + } + } + + namespace GFramework.Core.Architectures + { + public abstract class Architecture : GFramework.Core.Abstractions.Architectures.IArchitecture + { + protected abstract void OnInitialize(); + + public virtual T RegisterModel(T model) where T : GFramework.Core.Abstractions.Model.IModel => model; + + public virtual void RegisterModel(Action onCreated = null) + where T : class, GFramework.Core.Abstractions.Model.IModel + { + } + + public virtual T RegisterSystem(T system) where T : GFramework.Core.Abstractions.Systems.ISystem => system; + + public virtual void RegisterSystem(Action onCreated = null) + where T : class, GFramework.Core.Abstractions.Systems.ISystem + { + } + + public virtual T RegisterUtility(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility => utility; + + public virtual void RegisterUtility(Action onCreated = null) + where T : class, GFramework.Core.Abstractions.Utility.IUtility + { + } + + public virtual GFramework.Core.Abstractions.Architectures.IArchitectureModule InstallModule( + GFramework.Core.Abstractions.Architectures.IArchitectureModule module) + { + module.Install(this); + return module; + } + } + } + + namespace GFramework.Core.Extensions + { + public static class ContextAwareServiceExtensions + { + public static TModel GetModel(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException(); + + public static IReadOnlyList GetModels(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException(); + + public static TSystem GetSystem(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException(); + + public static IReadOnlyList GetSystems(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException(); + + public static TUtility GetUtility(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException(); + + public static IReadOnlyList GetUtilities(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) + where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException(); + } + } + + namespace GFramework.SourceGenerators.Abstractions.Rule + { + public sealed class GetModelAttribute : Attribute { } + public sealed class GetModelsAttribute : Attribute { } + public sealed class GetSystemAttribute : Attribute { } + public sealed class GetSystemsAttribute : Attribute { } + public sealed class GetUtilityAttribute : Attribute { } + public sealed class GetUtilitiesAttribute : Attribute { } + } + """; [Test] public async Task Reports_Warning_When_FieldInjectedModel_Is_Not_Registered() @@ -366,7 +366,8 @@ public sealed class ContextRegistrationAnalyzerTests } [Test] - public async Task Does_Not_Report_When_Inherited_OnInitialize_Calls_Virtual_Helper_Overridden_In_Derived_Architecture() + public async Task + Does_Not_Report_When_Inherited_OnInitialize_Calls_Virtual_Helper_Overridden_In_Derived_Architecture() { await AnalyzerTestDriver.RunAsync( Wrap(""" diff --git a/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs index 964bba4a..ae44a8ed 100644 --- a/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Architectures/AutoRegisterModuleGeneratorTests.cs @@ -1,4 +1,4 @@ -using GFramework.SourceGenerators.Architectures; +using GFramework.Core.SourceGenerators.Architectures; using GFramework.SourceGenerators.Tests.Core; namespace GFramework.SourceGenerators.Tests.Architectures; @@ -180,42 +180,42 @@ public class AutoRegisterModuleGeneratorTests """; const string partASource = """ - namespace TestApp - { - using GFramework.SourceGenerators.Abstractions.Architectures; + namespace TestApp + { + using GFramework.SourceGenerators.Abstractions.Architectures; - // Padding ensures this attribute lives later in the file than the attributes in PartB. - // The generator should still place it first because PartA sorts before PartB. - // padding 01 - // padding 02 - // padding 03 - // padding 04 - // padding 05 - // padding 06 - // padding 07 - // padding 08 - // padding 09 - // padding 10 - [AutoRegisterModule] - [RegisterUtility(typeof(AudioUtility))] - public partial class GameplayModule - { - } - } - """; + // Padding ensures this attribute lives later in the file than the attributes in PartB. + // The generator should still place it first because PartA sorts before PartB. + // padding 01 + // padding 02 + // padding 03 + // padding 04 + // padding 05 + // padding 06 + // padding 07 + // padding 08 + // padding 09 + // padding 10 + [AutoRegisterModule] + [RegisterUtility(typeof(AudioUtility))] + public partial class GameplayModule + { + } + } + """; const string partBSource = """ - namespace TestApp - { - using GFramework.SourceGenerators.Abstractions.Architectures; + namespace TestApp + { + using GFramework.SourceGenerators.Abstractions.Architectures; - [RegisterSystem(typeof(CombatSystem))] - [RegisterModel(typeof(PlayerModel))] - public partial class GameplayModule - { - } - } - """; + [RegisterSystem(typeof(CombatSystem))] + [RegisterModel(typeof(PlayerModel))] + public partial class GameplayModule + { + } + } + """; const string expected = """ // @@ -247,7 +247,8 @@ public class AutoRegisterModuleGeneratorTests }, GeneratedSources = { - (typeof(AutoRegisterModuleGenerator), "TestApp_GameplayModule.AutoRegisterModule.g.cs", NormalizeLineEndings(expected)) + (typeof(AutoRegisterModuleGenerator), "TestApp_GameplayModule.AutoRegisterModule.g.cs", + NormalizeLineEndings(expected)) } }, DisabledDiagnostics = { "GF_Common_Trace_001" } diff --git a/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs index 37588603..bb29762a 100644 --- a/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Bases/PriorityGeneratorSnapshotTests.cs @@ -1,7 +1,6 @@ using System.IO; -using GFramework.SourceGenerators.Bases; +using GFramework.Core.SourceGenerators.Bases; using GFramework.SourceGenerators.Tests.Core; -using NUnit.Framework; namespace GFramework.SourceGenerators.Tests.Bases; @@ -212,4 +211,4 @@ public class PriorityGeneratorSnapshotTests "PriorityGenerator", "GenericClass")); } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Config/SchemaGeneratorTestDriver.cs b/GFramework.SourceGenerators.Tests/Config/SchemaGeneratorTestDriver.cs index 4da9519a..c8f5a4e4 100644 --- a/GFramework.SourceGenerators.Tests/Config/SchemaGeneratorTestDriver.cs +++ b/GFramework.SourceGenerators.Tests/Config/SchemaGeneratorTestDriver.cs @@ -1,7 +1,6 @@ using System.Collections.Immutable; using System.IO; -using GFramework.SourceGenerators.Config; -using Microsoft.CodeAnalysis.CSharp; +using GFramework.Game.SourceGenerators.Config; namespace GFramework.SourceGenerators.Tests.Config; @@ -85,4 +84,4 @@ public static class SchemaGeneratorTestDriver return _text; } } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs index 4077c980..5d97e998 100644 --- a/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs @@ -1,5 +1,5 @@ using System.Reflection; -using GFramework.SourceGenerators.Cqrs; +using GFramework.Cqrs.SourceGenerators.Cqrs; using GFramework.SourceGenerators.Tests.Core; namespace GFramework.SourceGenerators.Tests.Cqrs; @@ -252,6 +252,84 @@ public class CqrsHandlerRegistryGeneratorTests """; + private const string ExternalAssemblyPreciseLookupExpected = """ + // + #nullable enable + + [assembly: global::GFramework.Cqrs.CqrsHandlerRegistryAttribute(typeof(global::GFramework.Generated.Cqrs.__GFrameworkGeneratedCqrsHandlerRegistry))] + + namespace GFramework.Generated.Cqrs; + + internal sealed class __GFrameworkGeneratedCqrsHandlerRegistry : global::GFramework.Cqrs.ICqrsHandlerRegistry + { + public void Register(global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::GFramework.Core.Abstractions.Logging.ILogger logger) + { + if (services is null) + throw new global::System.ArgumentNullException(nameof(services)); + if (logger is null) + throw new global::System.ArgumentNullException(nameof(logger)); + + var registryAssembly = typeof(global::GFramework.Generated.Cqrs.__GFrameworkGeneratedCqrsHandlerRegistry).Assembly; + + var implementationType0 = typeof(global::TestApp.DerivedHandler); + if (implementationType0 is not null) + { + var serviceType0_0Argument0 = ResolveReferencedAssemblyType("Dependency, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Dep.VisibilityScope+ProtectedRequest"); + var serviceType0_0Argument1Element = ResolveReferencedAssemblyType("Dependency, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Dep.VisibilityScope+ProtectedResponse"); + if (serviceType0_0Argument0 is not null && serviceType0_0Argument1Element is not null) + { + var serviceType0_0 = typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<,>).MakeGenericType(serviceType0_0Argument0, serviceType0_0Argument1Element.MakeArrayType()); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient( + services, + serviceType0_0, + implementationType0); + logger.Debug("Registered CQRS handler TestApp.DerivedHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler."); + } + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient( + services, + typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler), + implementationType0); + logger.Debug("Registered CQRS handler TestApp.DerivedHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler."); + } + } + + private static global::System.Type? ResolveReferencedAssemblyType(string assemblyIdentity, string typeMetadataName) + { + var assembly = ResolveReferencedAssembly(assemblyIdentity); + return assembly?.GetType(typeMetadataName, throwOnError: false, ignoreCase: false); + } + + private static global::System.Reflection.Assembly? ResolveReferencedAssembly(string assemblyIdentity) + { + global::System.Reflection.AssemblyName targetAssemblyName; + try + { + targetAssemblyName = new global::System.Reflection.AssemblyName(assemblyIdentity); + } + catch + { + return null; + } + + foreach (var assembly in global::System.AppDomain.CurrentDomain.GetAssemblies()) + { + if (global::System.Reflection.AssemblyName.ReferenceMatchesDefinition(targetAssemblyName, assembly.GetName())) + return assembly; + } + + try + { + return global::System.Reflection.Assembly.Load(targetAssemblyName); + } + catch + { + return null; + } + } + } + + """; + /// /// 验证生成器会为当前程序集中的 request、notification 和 stream 处理器生成稳定顺序的注册器。 /// @@ -923,37 +1001,9 @@ public class CqrsHandlerRegistryGeneratorTests contractsReference, dependencyReference); - Assert.Multiple(() => - { - Assert.That( - generatedSource, - Does.Contain("var implementationType0 = typeof(global::TestApp.DerivedHandler);")); - Assert.That( - generatedSource, - Does.Contain( - "ResolveReferencedAssemblyType(\"Dependency\", \"Dep.VisibilityScope+ProtectedRequest\")")); - Assert.That( - generatedSource, - Does.Contain( - "ResolveReferencedAssemblyType(\"Dependency\", \"Dep.VisibilityScope+ProtectedResponse\")")); - Assert.That( - generatedSource, - Does.Contain( - "typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler)")); - Assert.That( - generatedSource, - Does.Contain("ResolveReferencedAssembly(string assemblyName)")); - Assert.That( - generatedSource, - Does.Not.Contain("knownServiceTypes0")); - Assert.That( - generatedSource, - Does.Not.Contain("RegisterRemainingReflectedHandlerInterfaces")); - Assert.That( - generatedSource, - Does.Not.Contain( - "// Remaining runtime interface discovery target:")); - }); + Assert.That( + generatedSource, + Is.EqualTo(ExternalAssemblyPreciseLookupExpected)); } /// diff --git a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs index 27d73c11..f9ddf5c0 100644 --- a/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Enums/EnumExtensionsGeneratorSnapshotTests.cs @@ -1,7 +1,6 @@ using System.IO; -using GFramework.SourceGenerators.Enums; +using GFramework.Core.SourceGenerators.Enums; using GFramework.SourceGenerators.Tests.Core; -using NUnit.Framework; namespace GFramework.SourceGenerators.Tests.Enums; @@ -206,4 +205,4 @@ public class EnumExtensionsGeneratorSnapshotTests "EnumExtensionsGenerator", "DisableIsInMethod")); } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs index d90412e8..e1263a0f 100644 --- a/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs @@ -1,7 +1,6 @@ using System.IO; -using GFramework.SourceGenerators.Logging; +using GFramework.Core.SourceGenerators.Logging; using GFramework.SourceGenerators.Tests.Core; -using NUnit.Framework; namespace GFramework.SourceGenerators.Tests.Logging; @@ -589,4 +588,4 @@ public class LoggerGeneratorSnapshotTests "LoggerGenerator", "GenericClass")); } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs index dba9faa1..415a7f09 100644 --- a/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/Rule/ContextAwareGeneratorSnapshotTests.cs @@ -1,7 +1,6 @@ using System.IO; -using GFramework.SourceGenerators.Rule; +using GFramework.Core.SourceGenerators.Rule; using GFramework.SourceGenerators.Tests.Core; -using NUnit.Framework; namespace GFramework.SourceGenerators.Tests.Rule; @@ -93,4 +92,4 @@ public class ContextAwareGeneratorSnapshotTests "snapshots", "ContextAwareGenerator")); } -} \ No newline at end of file +} diff --git a/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs b/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs index c8804f58..d16806e6 100644 --- a/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs +++ b/GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs @@ -1,4 +1,4 @@ -using GFramework.SourceGenerators.Rule; +using GFramework.Core.SourceGenerators.Rule; using GFramework.SourceGenerators.Tests.Core; namespace GFramework.SourceGenerators.Tests.Rule; diff --git a/GFramework.csproj b/GFramework.csproj index 12324d1c..33baacae 100644 --- a/GFramework.csproj +++ b/GFramework.csproj @@ -30,19 +30,18 @@ - GFramework.SorceGenerators\logging\README.md + GFramework.Core.SourceGenerators\logging\README.md - GFramework.SorceGenerators\README.md + GFramework.Core.SourceGenerators\README.md - GFramework.SorceGenerators\AnalyzerReleases.Shipped.md + GFramework.Core.SourceGenerators\AnalyzerReleases.Shipped.md - GFramework.SorceGenerators\AnalyzerReleases.Unshipped.md + GFramework.Core.SourceGenerators\AnalyzerReleases.Unshipped.md - @@ -82,16 +81,15 @@ - GFramework.SorceGenerators\enums\EnumExtensionsGenerator.cs + GFramework.Core.SourceGenerators\enums\EnumExtensionsGenerator.cs - GFramework.SorceGenerators\logging\Diagnostic.cs + GFramework.Core.SourceGenerators\logging\Diagnostic.cs - GFramework.SorceGenerators\logging\LoggerGenerator.cs + GFramework.Core.SourceGenerators\logging\LoggerGenerator.cs - @@ -126,7 +124,6 @@ - diff --git a/README.md b/README.md index 19f04dae..4fe20e29 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,11 @@ dotnet add package GeWuYou.GFramework.Game.Abstractions # Godot 集成(仅 Godot 项目需要) dotnet add package GeWuYou.GFramework.Godot -# 源码生成器(可选,但推荐) -dotnet add package GeWuYou.GFramework.SourceGenerators +# 按场景选择源码生成器(可选,但推荐) +dotnet add package GeWuYou.GFramework.Core.SourceGenerators +dotnet add package GeWuYou.GFramework.Game.SourceGenerators +dotnet add package GeWuYou.GFramework.Godot.SourceGenerators +dotnet add package GeWuYou.GFramework.Cqrs.SourceGenerators ``` ## 可选模块导入 diff --git a/docs/zh-CN/core/cqrs.md b/docs/zh-CN/core/cqrs.md index c488ff19..c0357fa5 100644 --- a/docs/zh-CN/core/cqrs.md +++ b/docs/zh-CN/core/cqrs.md @@ -247,6 +247,8 @@ public class GameArchitecture : Architecture handler。 `RegisterCqrsPipelineBehavior()` 是唯一保留的公开入口;旧的 `Mediator` 兼容别名与扩展已移除,不再继续维护。 +如果你正在从旧版本迁移,显式替换关系就是 +`RegisterMediatorBehavior() -> RegisterCqrsPipelineBehavior()`。 当前接口支持两种形式: - 开放泛型行为,例如 `LoggingBehavior<,>`,用于匹配所有请求 diff --git a/docs/zh-CN/game/config-system.md b/docs/zh-CN/game/config-system.md index 5725d2c6..c00f2a2c 100644 --- a/docs/zh-CN/game/config-system.md +++ b/docs/zh-CN/game/config-system.md @@ -180,7 +180,9 @@ GameProject/ 如果你使用打包后的 NuGet,而不是仓库内项目引用,原则保持不变: - 运行时项目需要引用 `GeWuYou.GFramework.Game` -- 生成器项目需要引用 `GeWuYou.GFramework.SourceGenerators` +- 配置 schema 生成器需要引用 `GeWuYou.GFramework.Game.SourceGenerators` +- 如果同一项目还会使用 `[Log]`、`[ContextAware]`、`[GetSystem]` 等 Core 侧生成器特性,再额外引用 + `GeWuYou.GFramework.Core.SourceGenerators` - schema 目录默认仍然是 `schemas/` 如果你的 schema 不放在默认目录,可以在项目文件里覆盖: diff --git a/docs/zh-CN/getting-started/installation.md b/docs/zh-CN/getting-started/installation.md index c6b8618c..b99432de 100644 --- a/docs/zh-CN/getting-started/installation.md +++ b/docs/zh-CN/getting-started/installation.md @@ -6,13 +6,18 @@ GFramework 提供多种安装方式,您可以根据项目需求选择合适的 GFramework 采用模块化设计,不同包提供不同的功能: -| 包名 | 说明 | 适用场景 | -|---------------------------------------|---------|-----------| -| `GeWuYou.GFramework` | 聚合元包 | 快速试用、原型开发 | -| `GeWuYou.GFramework.Core` | 核心框架 | 生产项目推荐 | -| `GeWuYou.GFramework.Game` | 游戏模块 | 需要游戏特定功能 | -| `GeWuYou.GFramework.Godot` | Godot集成 | Godot项目必需 | -| `GeWuYou.GFramework.SourceGenerators` | 源码生成器 | 推荐安装 | +| 包名 | 说明 | 适用场景 | +|---------------------------------------------|-------------|--------------------------------| +| `GeWuYou.GFramework` | 聚合元包 | 快速试用、原型开发 | +| `GeWuYou.GFramework.Core` | 核心框架 | 生产项目推荐 | +| `GeWuYou.GFramework.Game` | 游戏模块 | 需要游戏特定功能 | +| `GeWuYou.GFramework.Godot` | Godot集成 | Godot项目必需 | +| `GeWuYou.GFramework.Core.SourceGenerators` | Core 源码生成器 | `[Log]`、`[ContextAware]`、架构注入等 | +| `GeWuYou.GFramework.Game.SourceGenerators` | Game 源码生成器 | 配置 schema / 配表生成 | +| `GeWuYou.GFramework.Godot.SourceGenerators` | Godot 源码生成器 | Godot 节点、UI、项目元数据生成 | +| `GeWuYou.GFramework.Cqrs.SourceGenerators` | CQRS 源码生成器 | 处理器注册表生成 | + +当前 NuGet 发布按模块拆分 source generator 包,不存在 `GeWuYou.GFramework.SourceGenerators` 聚合包。 ## 安装方式 @@ -30,8 +35,17 @@ dotnet add package GeWuYou.GFramework.Game.Abstractions # Godot 集成(仅 Godot 项目需要) dotnet add package GeWuYou.GFramework.Godot -# 源码生成器(可选,但推荐) -dotnet add package GeWuYou.GFramework.SourceGenerators +# Core 侧源码生成器([Log] / [ContextAware] / [GetSystem] 等) +dotnet add package GeWuYou.GFramework.Core.SourceGenerators + +# Game 配置 schema 生成器 +dotnet add package GeWuYou.GFramework.Game.SourceGenerators + +# Godot 生成器(仅 Godot 项目需要) +dotnet add package GeWuYou.GFramework.Godot.SourceGenerators + +# CQRS 处理器注册生成器(仅使用 CQRS source generator 时需要) +dotnet add package GeWuYou.GFramework.Cqrs.SourceGenerators ``` ### 2. 使用 PackageReference @@ -56,8 +70,14 @@ dotnet add package GeWuYou.GFramework.SourceGenerators - - + + + + @@ -183,6 +203,8 @@ dotnet build 检查: -- 确保安装了 `GeWuYou.GFramework.SourceGenerators` +- 确保安装了与你正在使用的特性对应的拆分生成器包,例如: + `GeWuYou.GFramework.Core.SourceGenerators`、`GeWuYou.GFramework.Game.SourceGenerators`、 + `GeWuYou.GFramework.Godot.SourceGenerators` 或 `GeWuYou.GFramework.Cqrs.SourceGenerators` - 重启 IDE - 清理并重新构建项目 diff --git a/docs/zh-CN/source-generators/index.md b/docs/zh-CN/source-generators/index.md index ea62aad0..224ed96a 100644 --- a/docs/zh-CN/source-generators/index.md +++ b/docs/zh-CN/source-generators/index.md @@ -30,7 +30,16 @@ GFramework.SourceGenerators 是 GFramework 框架的源代码生成器包,通 ## 概述 -GFramework.SourceGenerators 利用 Roslyn 源代码生成器技术,在编译时分析你的代码并自动生成常用的样板代码,让开发者专注于业务逻辑而不是重复的模板代码。 +GFramework 的 source generators 利用 Roslyn 源代码生成器技术,在编译时分析你的代码并自动生成常用的样板代码,让开发者专注于业务逻辑而不是重复的模板代码。 + +当前 NuGet 发布按模块拆分为: + +- `GeWuYou.GFramework.Core.SourceGenerators` +- `GeWuYou.GFramework.Game.SourceGenerators` +- `GeWuYou.GFramework.Godot.SourceGenerators` +- `GeWuYou.GFramework.Cqrs.SourceGenerators` + +不存在 `GeWuYou.GFramework.SourceGenerators` 或 `GeWuYou.GFramework.SourceGenerators.Attributes` 这类聚合包。 ### 核心设计理念 @@ -74,22 +83,30 @@ GFramework.SourceGenerators 利用 Roslyn 源代码生成器技术,在编译 ### NuGet 包安装 ```xml - net6.0 - - + + ``` +如果你只使用 Godot 生成器或 CQRS 处理器注册生成器,请把上面的包替换为对应的 +`GeWuYou.GFramework.Godot.SourceGenerators` 或 `GeWuYou.GFramework.Cqrs.SourceGenerators`。 +这些拆分包会同时带上各自需要的 abstractions 程序集,不需要再额外安装单独的 `*.Attributes` 包。 + ### Config Schema 文件约定 -当项目引用 `GeWuYou.GFramework.SourceGenerators` 的打包产物时,生成器会默认从 `schemas/**/*.schema.json` 收集配置 schema +当项目引用 `GeWuYou.GFramework.Game.SourceGenerators` 的打包产物时,生成器会默认从 `schemas/**/*.schema.json` 收集配置 +schema 文件并作为 `AdditionalFiles` 输入。 这意味着消费者项目通常只需要维护如下结构: @@ -150,7 +167,7 @@ Config Schema 生成器会扫描 `*.schema.json` 文件,并生成: ### 基础使用 ```csharp -using GFramework.SourceGenerators.Attributes; +using GFramework.SourceGenerators.Abstractions.Logging; [Log] public partial class PlayerController diff --git a/docs/zh-CN/tutorials/basic/02-project-setup.md b/docs/zh-CN/tutorials/basic/02-project-setup.md index 2df9a3a6..41022e99 100644 --- a/docs/zh-CN/tutorials/basic/02-project-setup.md +++ b/docs/zh-CN/tutorials/basic/02-project-setup.md @@ -74,8 +74,11 @@ dotnet add package GeWuYou.GFramework # Godot 集成 dotnet add package GeWuYou.GFramework.Godot -# 源码生成器(可选,但推荐) -dotnet add package GeWuYou.GFramework.SourceGenerators +# Core 侧源码生成器([Log] / [ContextAware] 等) +dotnet add package GeWuYou.GFramework.Core.SourceGenerators + +# Godot 侧源码生成器([GetNode] / [AutoUiPage] 等) +dotnet add package GeWuYou.GFramework.Godot.SourceGenerators ``` ::: details 分包安装(了解即可) @@ -93,8 +96,11 @@ dotnet add package GeWuYou.GFramework.Game.Abstractions # Godot 集成 dotnet add package GeWuYou.GFramework.Godot -# 源码生成器 -dotnet add package GeWuYou.GFramework.SourceGenerators +# Core 侧源码生成器 +dotnet add package GeWuYou.GFramework.Core.SourceGenerators + +# Godot 侧源码生成器 +dotnet add package GeWuYou.GFramework.Godot.SourceGenerators ``` ::: @@ -108,7 +114,8 @@ dotnet add package GeWuYou.GFramework.SourceGenerators 3. 安装以下包: - `GeWuYou.GFramework` - `GeWuYou.GFramework.Godot` - - `GeWuYou.GFramework.SourceGenerators` + - `GeWuYou.GFramework.Core.SourceGenerators` + - `GeWuYou.GFramework.Godot.SourceGenerators` ![NuGet 包管理](../assets/basic/image-20260211211756993.png)