docs(config): 添加游戏内容配置系统文档

- 新增 CQRS 架构模式详细文档,包括命令查询职责分离核心概念
- 添加命令、查询、处理器、请求分发器等基本用法示例
- 包含高级用法如通知、管道行为、流式处理等完整功能介绍
- 提供最佳实践指南和常见问题解决方案
- 添加游戏内容配置系统文档,涵盖 YAML 配置源文件和 JSON Schema 结构描述
- 包含推荐目录结构、Schema 示例和 YAML 示例配置
- 提供完整的接入模板,包括 csproj 配置、启动帮助器和运行时读取模板
- 添加 Godot 文本配置桥接、热重载和 Architecture 接入等高级功能说明
This commit is contained in:
GeWuYou 2026-04-16 21:01:01 +08:00
parent 09f751a4f7
commit 0cf4945e78
51 changed files with 416 additions and 293 deletions

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Architectures; namespace GFramework.Core.SourceGenerators.Abstractions.Architectures;
/// <summary> /// <summary>
/// 标记架构模块类型Source Generator 会根据注册特性生成 <c>Install</c> 方法。 /// 标记架构模块类型Source Generator 会根据注册特性生成 <c>Install</c> 方法。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Architectures; namespace GFramework.Core.SourceGenerators.Abstractions.Architectures;
/// <summary> /// <summary>
/// 声明架构模块需要自动注册的模型类型。 /// 声明架构模块需要自动注册的模型类型。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Architectures; namespace GFramework.Core.SourceGenerators.Abstractions.Architectures;
/// <summary> /// <summary>
/// 声明架构模块需要自动注册的系统类型。 /// 声明架构模块需要自动注册的系统类型。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Architectures; namespace GFramework.Core.SourceGenerators.Abstractions.Architectures;
/// <summary> /// <summary>
/// 声明架构模块需要自动注册的工具类型。 /// 声明架构模块需要自动注册的工具类型。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Bases; namespace GFramework.Core.SourceGenerators.Abstractions.Bases;
/// <summary> /// <summary>
/// 标记类的优先级,自动生成 <c>GFramework.Core.Abstractions.Bases.IPrioritized</c> 接口实现。 /// 标记类的优先级,自动生成 <c>GFramework.Core.Abstractions.Bases.IPrioritized</c> 接口实现。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Enums; namespace GFramework.Core.SourceGenerators.Abstractions.Enums;
/// <summary> /// <summary>
/// 标注在 enum 上Source Generator 会为该 enum 生成扩展方法。 /// 标注在 enum 上Source Generator 会为该 enum 生成扩展方法。

View File

@ -1,5 +1,5 @@
#nullable enable #nullable enable
namespace GFramework.SourceGenerators.Abstractions.Logging; namespace GFramework.Core.SourceGenerators.Abstractions.Logging;
/// <summary> /// <summary>
/// 标注在类上Source Generator 会为该类自动生成一个日志记录器字段。 /// 标注在类上Source Generator 会为该类自动生成一个日志记录器字段。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Rule; namespace GFramework.Core.SourceGenerators.Abstractions.Rule;
/// <summary> /// <summary>
/// 标记该类需要自动实现 IContextAware /// 标记该类需要自动实现 IContextAware

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Rule; namespace GFramework.Core.SourceGenerators.Abstractions.Rule;
/// <summary> /// <summary>
/// 标记类需要自动推断并注入上下文相关字段。 /// 标记类需要自动推断并注入上下文相关字段。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Rule; namespace GFramework.Core.SourceGenerators.Abstractions.Rule;
/// <summary> /// <summary>
/// 标记字段需要自动注入单个模型实例。 /// 标记字段需要自动注入单个模型实例。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Rule; namespace GFramework.Core.SourceGenerators.Abstractions.Rule;
/// <summary> /// <summary>
/// 标记字段需要自动注入模型集合。 /// 标记字段需要自动注入模型集合。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Rule; namespace GFramework.Core.SourceGenerators.Abstractions.Rule;
/// <summary> /// <summary>
/// 标记字段需要自动注入单个服务实例。 /// 标记字段需要自动注入单个服务实例。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Rule; namespace GFramework.Core.SourceGenerators.Abstractions.Rule;
/// <summary> /// <summary>
/// 标记字段需要自动注入服务集合。 /// 标记字段需要自动注入服务集合。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Rule; namespace GFramework.Core.SourceGenerators.Abstractions.Rule;
/// <summary> /// <summary>
/// 标记字段需要自动注入单个系统实例。 /// 标记字段需要自动注入单个系统实例。

View File

@ -1,8 +1,22 @@
namespace GFramework.SourceGenerators.Abstractions.Rule; namespace GFramework.Core.SourceGenerators.Abstractions.Rule;
/// <summary> /// <summary>
/// 标记字段需要自动注入系统集合。 /// 标记字段需要自动注入系统集合。
/// </summary> /// </summary>
/// <remarks>
/// Source Generator 会为标记字段生成从当前架构上下文收集系统实例的注入代码,用于避免在组件内部重复书写
/// <c>GetSystems()</c> 一类的样板访问逻辑。
/// 被标记字段应声明为可承载多个系统实例的类型,例如 <c>IEnumerable&lt;ISystem&gt;</c> 或兼容集合接口。
/// </remarks>
/// <example>
/// <code>
/// public partial class CombatPanel : IContextAware
/// {
/// [GetSystems]
/// private IEnumerable&lt;ISystem&gt; _systems = Array.Empty&lt;ISystem&gt;();
/// }
/// </code>
/// </example>
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class GetSystemsAttribute : Attribute public sealed class GetSystemsAttribute : Attribute
{ {

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Rule; namespace GFramework.Core.SourceGenerators.Abstractions.Rule;
/// <summary> /// <summary>
/// 标记字段需要自动注入工具集合。 /// 标记字段需要自动注入工具集合。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Abstractions.Rule; namespace GFramework.Core.SourceGenerators.Abstractions.Rule;
/// <summary> /// <summary>
/// 标记字段需要自动注入单个工具实例。 /// 标记字段需要自动注入单个工具实例。

View File

@ -1,9 +1,9 @@
using GFramework.Core.SourceGenerators.Diagnostics;
using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Constants;
using GFramework.SourceGenerators.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Operations;
namespace GFramework.SourceGenerators.Analyzers; namespace GFramework.Core.SourceGenerators.Analyzers;
/// <summary> /// <summary>
/// 分析 Context Get 使用点是否能在所属架构中找到静态可见的 Model、System、Utility 注册。 /// 分析 Context Get 使用点是否能在所属架构中找到静态可见的 Model、System、Utility 注册。

View File

@ -1,8 +1,8 @@
using GFramework.SourceGenerators.Diagnostics; using GFramework.Core.SourceGenerators.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Operations;
namespace GFramework.SourceGenerators.Analyzers; namespace GFramework.Core.SourceGenerators.Analyzers;
/// <summary> /// <summary>
/// 优先级使用分析器,检测应该使用 GetAllByPriority 而非 GetAll 的场景 /// 优先级使用分析器,检测应该使用 GetAllByPriority 而非 GetAll 的场景

View File

@ -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.Constants;
using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Diagnostics;
using GFramework.SourceGenerators.Common.Extensions; using GFramework.SourceGenerators.Common.Extensions;
using GFramework.SourceGenerators.Diagnostics;
namespace GFramework.SourceGenerators.Architectures; namespace GFramework.Core.SourceGenerators.Architectures;
/// <summary> /// <summary>
/// 为标记了 <see cref="AutoRegisterModuleAttribute" /> 的模块生成固定顺序的组件注册代码。 /// 为标记了 <see cref="AutoRegisterModuleAttribute" /> 的模块生成固定顺序的组件注册代码。

View File

@ -1,8 +1,8 @@
using GFramework.Core.SourceGenerators.Diagnostics;
using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Constants;
using GFramework.SourceGenerators.Common.Generator; using GFramework.SourceGenerators.Common.Generator;
using GFramework.SourceGenerators.Diagnostics;
namespace GFramework.SourceGenerators.Bases; namespace GFramework.Core.SourceGenerators.Bases;
/// <summary> /// <summary>
/// Priority 特性生成器,为标记了 [Priority] 的类自动生成 IPrioritized 接口实现 /// Priority 特性生成器,为标记了 [Priority] 的类自动生成 IPrioritized 接口实现

View File

@ -1,6 +1,6 @@
using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Constants;
namespace GFramework.SourceGenerators.Diagnostics; namespace GFramework.Core.SourceGenerators.Diagnostics;
internal static class AutoRegisterModuleDiagnostics internal static class AutoRegisterModuleDiagnostics
{ {

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Diagnostics; namespace GFramework.Core.SourceGenerators.Diagnostics;
/// <summary> /// <summary>
/// 提供与上下文感知相关的诊断规则定义 /// 提供与上下文感知相关的诊断规则定义

View File

@ -1,6 +1,6 @@
using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Constants;
namespace GFramework.SourceGenerators.Diagnostics; namespace GFramework.Core.SourceGenerators.Diagnostics;
/// <summary> /// <summary>
/// 提供 Context Get 注入生成器相关诊断。 /// 提供 Context Get 注入生成器相关诊断。

View File

@ -1,6 +1,6 @@
using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Constants;
namespace GFramework.SourceGenerators.Diagnostics; namespace GFramework.Core.SourceGenerators.Diagnostics;
/// <summary> /// <summary>
/// 提供 Context Get 注册可见性分析相关诊断。 /// 提供 Context Get 注册可见性分析相关诊断。

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Diagnostics; namespace GFramework.Core.SourceGenerators.Diagnostics;
/// <summary> /// <summary>
/// 提供诊断描述符的静态类用于GFramework日志生成器的编译时检查 /// 提供诊断描述符的静态类用于GFramework日志生成器的编译时检查

View File

@ -1,4 +1,4 @@
namespace GFramework.SourceGenerators.Diagnostics; namespace GFramework.Core.SourceGenerators.Diagnostics;
/// <summary> /// <summary>
/// Priority 特性相关的诊断信息 /// Priority 特性相关的诊断信息

View File

@ -2,7 +2,7 @@
using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Diagnostics;
using GFramework.SourceGenerators.Common.Generator; using GFramework.SourceGenerators.Common.Generator;
namespace GFramework.SourceGenerators.Enums; namespace GFramework.Core.SourceGenerators.Enums;
/// <summary> /// <summary>
/// 枚举扩展方法生成器,用于自动生成枚举相关的扩展方法 /// 枚举扩展方法生成器,用于自动生成枚举相关的扩展方法

View File

@ -1,9 +1,9 @@
using GFramework.SourceGenerators.Abstractions.Logging; using GFramework.Core.SourceGenerators.Abstractions.Logging;
using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Constants;
using GFramework.SourceGenerators.Common.Extensions; using GFramework.SourceGenerators.Common.Extensions;
using GFramework.SourceGenerators.Common.Generator; using GFramework.SourceGenerators.Common.Generator;
namespace GFramework.SourceGenerators.Logging; namespace GFramework.Core.SourceGenerators.Logging;
/// <summary> /// <summary>
/// 日志生成器用于为标记了LogAttribute的类自动生成日志字段 /// 日志生成器用于为标记了LogAttribute的类自动生成日志字段

View File

@ -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.Diagnostics;
using GFramework.SourceGenerators.Common.Generator; using GFramework.SourceGenerators.Common.Generator;
using GFramework.SourceGenerators.Diagnostics;
namespace GFramework.SourceGenerators.Rule; namespace GFramework.Core.SourceGenerators.Rule;
/// <summary> /// <summary>
/// 上下文感知生成器用于为标记了ContextAware特性的类自动生成IContextAware接口实现 /// 上下文感知生成器用于为标记了ContextAware特性的类自动生成IContextAware接口实现

View File

@ -1,10 +1,10 @@
using GFramework.Core.SourceGenerators.Diagnostics;
using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Constants;
using GFramework.SourceGenerators.Common.Diagnostics; using GFramework.SourceGenerators.Common.Diagnostics;
using GFramework.SourceGenerators.Common.Extensions; using GFramework.SourceGenerators.Common.Extensions;
using GFramework.SourceGenerators.Common.Info; using GFramework.SourceGenerators.Common.Info;
using GFramework.SourceGenerators.Diagnostics;
namespace GFramework.SourceGenerators.Rule; namespace GFramework.Core.SourceGenerators.Rule;
/// <summary> /// <summary>
/// 为上下文感知类生成 Core 上下文 Get 注入方法。 /// 为上下文感知类生成 Core 上下文 Get 注入方法。

View File

@ -1,6 +1,6 @@
using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Constants;
namespace GFramework.SourceGenerators.Cqrs; namespace GFramework.Cqrs.SourceGenerators.Cqrs;
/// <summary> /// <summary>
/// 为当前编译程序集生成 CQRS 处理器注册器,以减少运行时的程序集反射扫描成本。 /// 为当前编译程序集生成 CQRS 处理器注册器,以减少运行时的程序集反射扫描成本。
@ -347,7 +347,7 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
} }
runtimeTypeReference = RuntimeTypeReferenceSpec.FromExternalReflectionLookup( runtimeTypeReference = RuntimeTypeReferenceSpec.FromExternalReflectionLookup(
namedType.ContainingAssembly.Identity.Name, namedType.ContainingAssembly.Identity.ToString(),
GetReflectionTypeMetadataName(namedType)); GetReflectionTypeMetadataName(namedType));
return true; return true;
} }
@ -396,7 +396,7 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
} }
genericTypeDefinitionReference = RuntimeTypeReferenceSpec.FromExternalReflectionLookup( genericTypeDefinitionReference = RuntimeTypeReferenceSpec.FromExternalReflectionLookup(
genericTypeDefinition.ContainingAssembly.Identity.Name, genericTypeDefinition.ContainingAssembly.Identity.ToString(),
GetReflectionTypeMetadataName(genericTypeDefinition)); GetReflectionTypeMetadataName(genericTypeDefinition));
return true; return true;
} }
@ -951,28 +951,39 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
if (includeExternalAssemblyTypeLookupHelpers) if (includeExternalAssemblyTypeLookupHelpers)
{ {
builder.AppendLine( 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(" {");
builder.AppendLine(" var assembly = ResolveReferencedAssembly(assemblyName);"); builder.AppendLine(" var assembly = ResolveReferencedAssembly(assemblyIdentity);");
builder.AppendLine( builder.AppendLine(
" return assembly?.GetType(typeMetadataName, throwOnError: false, ignoreCase: false);"); " return assembly?.GetType(typeMetadataName, throwOnError: false, ignoreCase: false);");
builder.AppendLine(" }"); builder.AppendLine(" }");
builder.AppendLine(); 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(" {");
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( builder.AppendLine(
" foreach (var assembly in global::System.AppDomain.CurrentDomain.GetAssemblies())"); " foreach (var assembly in global::System.AppDomain.CurrentDomain.GetAssemblies())");
builder.AppendLine(" {"); builder.AppendLine(" {");
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(" return assembly;");
builder.AppendLine(" }"); builder.AppendLine(" }");
builder.AppendLine(); builder.AppendLine();
builder.AppendLine(" try"); builder.AppendLine(" try");
builder.AppendLine(" {"); builder.AppendLine(" {");
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(" }");
builder.AppendLine(" catch"); builder.AppendLine(" catch");
builder.AppendLine(" {"); builder.AppendLine(" {");

View File

@ -1,6 +1,6 @@
using GFramework.SourceGenerators.Diagnostics; using GFramework.Game.SourceGenerators.Diagnostics;
namespace GFramework.SourceGenerators.Config; namespace GFramework.Game.SourceGenerators.Config;
/// <summary> /// <summary>
/// 根据 AdditionalFiles 中的 JSON schema 生成配置类型和配置表包装。 /// 根据 AdditionalFiles 中的 JSON schema 生成配置类型和配置表包装。

View File

@ -1,6 +1,6 @@
using GFramework.SourceGenerators.Common.Constants; using GFramework.SourceGenerators.Common.Constants;
namespace GFramework.SourceGenerators.Diagnostics; namespace GFramework.Game.SourceGenerators.Diagnostics;
/// <summary> /// <summary>
/// 提供配置 schema 代码生成相关诊断。 /// 提供配置 schema 代码生成相关诊断。

View File

@ -7,6 +7,7 @@
<IncludeBuildOutput>false</IncludeBuildOutput> <IncludeBuildOutput>false</IncludeBuildOutput>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath> <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>

View File

@ -1,4 +1,4 @@
using GFramework.SourceGenerators.Analyzers; using GFramework.Core.SourceGenerators.Analyzers;
using GFramework.SourceGenerators.Tests.Core; using GFramework.SourceGenerators.Tests.Core;
namespace GFramework.SourceGenerators.Tests.Analyzers; namespace GFramework.SourceGenerators.Tests.Analyzers;
@ -9,128 +9,128 @@ namespace GFramework.SourceGenerators.Tests.Analyzers;
public sealed class ContextRegistrationAnalyzerTests public sealed class ContextRegistrationAnalyzerTests
{ {
private const string TestPreamble = """ private const string TestPreamble = """
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace GFramework.Core.Abstractions.Rule namespace GFramework.Core.Abstractions.Rule
{ {
public interface IContextAware { } public interface IContextAware { }
} }
namespace GFramework.Core.Abstractions.Model namespace GFramework.Core.Abstractions.Model
{ {
public interface IModel : GFramework.Core.Abstractions.Rule.IContextAware { } public interface IModel : GFramework.Core.Abstractions.Rule.IContextAware { }
} }
namespace GFramework.Core.Abstractions.Systems namespace GFramework.Core.Abstractions.Systems
{ {
public interface ISystem : GFramework.Core.Abstractions.Rule.IContextAware { } public interface ISystem : GFramework.Core.Abstractions.Rule.IContextAware { }
} }
namespace GFramework.Core.Abstractions.Utility namespace GFramework.Core.Abstractions.Utility
{ {
public interface IUtility : GFramework.Core.Abstractions.Rule.IContextAware { } public interface IUtility : GFramework.Core.Abstractions.Rule.IContextAware { }
} }
namespace GFramework.Core.Abstractions.Architectures namespace GFramework.Core.Abstractions.Architectures
{ {
public interface IArchitecture public interface IArchitecture
{ {
T RegisterModel<T>(T model) where T : GFramework.Core.Abstractions.Model.IModel; T RegisterModel<T>(T model) where T : GFramework.Core.Abstractions.Model.IModel;
void RegisterModel<T>(Action<T> onCreated = null) where T : class, GFramework.Core.Abstractions.Model.IModel; void RegisterModel<T>(Action<T> onCreated = null) where T : class, GFramework.Core.Abstractions.Model.IModel;
T RegisterSystem<T>(T system) where T : GFramework.Core.Abstractions.Systems.ISystem; T RegisterSystem<T>(T system) where T : GFramework.Core.Abstractions.Systems.ISystem;
void RegisterSystem<T>(Action<T> onCreated = null) where T : class, GFramework.Core.Abstractions.Systems.ISystem; void RegisterSystem<T>(Action<T> onCreated = null) where T : class, GFramework.Core.Abstractions.Systems.ISystem;
T RegisterUtility<T>(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility; T RegisterUtility<T>(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility;
void RegisterUtility<T>(Action<T> onCreated = null) where T : class, GFramework.Core.Abstractions.Utility.IUtility; void RegisterUtility<T>(Action<T> onCreated = null) where T : class, GFramework.Core.Abstractions.Utility.IUtility;
IArchitectureModule InstallModule(IArchitectureModule module); IArchitectureModule InstallModule(IArchitectureModule module);
} }
public interface IArchitectureModule public interface IArchitectureModule
{ {
void Install(IArchitecture architecture); void Install(IArchitecture architecture);
} }
public interface IArchitectureContext public interface IArchitectureContext
{ {
TModel GetModel<TModel>() where TModel : class, GFramework.Core.Abstractions.Model.IModel; TModel GetModel<TModel>() where TModel : class, GFramework.Core.Abstractions.Model.IModel;
IReadOnlyList<TModel> GetModels<TModel>() where TModel : class, GFramework.Core.Abstractions.Model.IModel; IReadOnlyList<TModel> GetModels<TModel>() where TModel : class, GFramework.Core.Abstractions.Model.IModel;
TSystem GetSystem<TSystem>() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem; TSystem GetSystem<TSystem>() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem;
IReadOnlyList<TSystem> GetSystems<TSystem>() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem; IReadOnlyList<TSystem> GetSystems<TSystem>() where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem;
TUtility GetUtility<TUtility>() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility; TUtility GetUtility<TUtility>() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility;
IReadOnlyList<TUtility> GetUtilities<TUtility>() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility; IReadOnlyList<TUtility> GetUtilities<TUtility>() where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility;
} }
} }
namespace GFramework.Core.Architectures namespace GFramework.Core.Architectures
{ {
public abstract class Architecture : GFramework.Core.Abstractions.Architectures.IArchitecture public abstract class Architecture : GFramework.Core.Abstractions.Architectures.IArchitecture
{ {
protected abstract void OnInitialize(); protected abstract void OnInitialize();
public virtual T RegisterModel<T>(T model) where T : GFramework.Core.Abstractions.Model.IModel => model; public virtual T RegisterModel<T>(T model) where T : GFramework.Core.Abstractions.Model.IModel => model;
public virtual void RegisterModel<T>(Action<T> onCreated = null) public virtual void RegisterModel<T>(Action<T> onCreated = null)
where T : class, GFramework.Core.Abstractions.Model.IModel where T : class, GFramework.Core.Abstractions.Model.IModel
{ {
} }
public virtual T RegisterSystem<T>(T system) where T : GFramework.Core.Abstractions.Systems.ISystem => system; public virtual T RegisterSystem<T>(T system) where T : GFramework.Core.Abstractions.Systems.ISystem => system;
public virtual void RegisterSystem<T>(Action<T> onCreated = null) public virtual void RegisterSystem<T>(Action<T> onCreated = null)
where T : class, GFramework.Core.Abstractions.Systems.ISystem where T : class, GFramework.Core.Abstractions.Systems.ISystem
{ {
} }
public virtual T RegisterUtility<T>(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility => utility; public virtual T RegisterUtility<T>(T utility) where T : GFramework.Core.Abstractions.Utility.IUtility => utility;
public virtual void RegisterUtility<T>(Action<T> onCreated = null) public virtual void RegisterUtility<T>(Action<T> onCreated = null)
where T : class, GFramework.Core.Abstractions.Utility.IUtility where T : class, GFramework.Core.Abstractions.Utility.IUtility
{ {
} }
public virtual GFramework.Core.Abstractions.Architectures.IArchitectureModule InstallModule( public virtual GFramework.Core.Abstractions.Architectures.IArchitectureModule InstallModule(
GFramework.Core.Abstractions.Architectures.IArchitectureModule module) GFramework.Core.Abstractions.Architectures.IArchitectureModule module)
{ {
module.Install(this); module.Install(this);
return module; return module;
} }
} }
} }
namespace GFramework.Core.Extensions namespace GFramework.Core.Extensions
{ {
public static class ContextAwareServiceExtensions public static class ContextAwareServiceExtensions
{ {
public static TModel GetModel<TModel>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) public static TModel GetModel<TModel>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware)
where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException(); where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException();
public static IReadOnlyList<TModel> GetModels<TModel>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) public static IReadOnlyList<TModel> GetModels<TModel>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware)
where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException(); where TModel : class, GFramework.Core.Abstractions.Model.IModel => throw new NotImplementedException();
public static TSystem GetSystem<TSystem>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) public static TSystem GetSystem<TSystem>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware)
where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException(); where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException();
public static IReadOnlyList<TSystem> GetSystems<TSystem>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) public static IReadOnlyList<TSystem> GetSystems<TSystem>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware)
where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException(); where TSystem : class, GFramework.Core.Abstractions.Systems.ISystem => throw new NotImplementedException();
public static TUtility GetUtility<TUtility>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) public static TUtility GetUtility<TUtility>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware)
where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException(); where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException();
public static IReadOnlyList<TUtility> GetUtilities<TUtility>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware) public static IReadOnlyList<TUtility> GetUtilities<TUtility>(this GFramework.Core.Abstractions.Rule.IContextAware contextAware)
where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException(); where TUtility : class, GFramework.Core.Abstractions.Utility.IUtility => throw new NotImplementedException();
} }
} }
namespace GFramework.SourceGenerators.Abstractions.Rule namespace GFramework.SourceGenerators.Abstractions.Rule
{ {
public sealed class GetModelAttribute : Attribute { } public sealed class GetModelAttribute : Attribute { }
public sealed class GetModelsAttribute : Attribute { } public sealed class GetModelsAttribute : Attribute { }
public sealed class GetSystemAttribute : Attribute { } public sealed class GetSystemAttribute : Attribute { }
public sealed class GetSystemsAttribute : Attribute { } public sealed class GetSystemsAttribute : Attribute { }
public sealed class GetUtilityAttribute : Attribute { } public sealed class GetUtilityAttribute : Attribute { }
public sealed class GetUtilitiesAttribute : Attribute { } public sealed class GetUtilitiesAttribute : Attribute { }
} }
"""; """;
[Test] [Test]
public async Task Reports_Warning_When_FieldInjectedModel_Is_Not_Registered() public async Task Reports_Warning_When_FieldInjectedModel_Is_Not_Registered()
@ -366,7 +366,8 @@ public sealed class ContextRegistrationAnalyzerTests
} }
[Test] [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<ContextRegistrationAnalyzer>.RunAsync( await AnalyzerTestDriver<ContextRegistrationAnalyzer>.RunAsync(
Wrap(""" Wrap("""

View File

@ -1,4 +1,4 @@
using GFramework.SourceGenerators.Architectures; using GFramework.Core.SourceGenerators.Architectures;
using GFramework.SourceGenerators.Tests.Core; using GFramework.SourceGenerators.Tests.Core;
namespace GFramework.SourceGenerators.Tests.Architectures; namespace GFramework.SourceGenerators.Tests.Architectures;
@ -180,42 +180,42 @@ public class AutoRegisterModuleGeneratorTests
"""; """;
const string partASource = """ const string partASource = """
namespace TestApp namespace TestApp
{ {
using GFramework.SourceGenerators.Abstractions.Architectures; using GFramework.SourceGenerators.Abstractions.Architectures;
// Padding ensures this attribute lives later in the file than the attributes in PartB. // 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. // The generator should still place it first because PartA sorts before PartB.
// padding 01 // padding 01
// padding 02 // padding 02
// padding 03 // padding 03
// padding 04 // padding 04
// padding 05 // padding 05
// padding 06 // padding 06
// padding 07 // padding 07
// padding 08 // padding 08
// padding 09 // padding 09
// padding 10 // padding 10
[AutoRegisterModule] [AutoRegisterModule]
[RegisterUtility(typeof(AudioUtility))] [RegisterUtility(typeof(AudioUtility))]
public partial class GameplayModule public partial class GameplayModule
{ {
} }
} }
"""; """;
const string partBSource = """ const string partBSource = """
namespace TestApp namespace TestApp
{ {
using GFramework.SourceGenerators.Abstractions.Architectures; using GFramework.SourceGenerators.Abstractions.Architectures;
[RegisterSystem(typeof(CombatSystem))] [RegisterSystem(typeof(CombatSystem))]
[RegisterModel(typeof(PlayerModel))] [RegisterModel(typeof(PlayerModel))]
public partial class GameplayModule public partial class GameplayModule
{ {
} }
} }
"""; """;
const string expected = """ const string expected = """
// <auto-generated /> // <auto-generated />
@ -247,7 +247,8 @@ public class AutoRegisterModuleGeneratorTests
}, },
GeneratedSources = GeneratedSources =
{ {
(typeof(AutoRegisterModuleGenerator), "TestApp_GameplayModule.AutoRegisterModule.g.cs", NormalizeLineEndings(expected)) (typeof(AutoRegisterModuleGenerator), "TestApp_GameplayModule.AutoRegisterModule.g.cs",
NormalizeLineEndings(expected))
} }
}, },
DisabledDiagnostics = { "GF_Common_Trace_001" } DisabledDiagnostics = { "GF_Common_Trace_001" }

View File

@ -1,7 +1,6 @@
using System.IO; using System.IO;
using GFramework.SourceGenerators.Bases; using GFramework.Core.SourceGenerators.Bases;
using GFramework.SourceGenerators.Tests.Core; using GFramework.SourceGenerators.Tests.Core;
using NUnit.Framework;
namespace GFramework.SourceGenerators.Tests.Bases; namespace GFramework.SourceGenerators.Tests.Bases;

View File

@ -1,7 +1,6 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.IO; using System.IO;
using GFramework.SourceGenerators.Config; using GFramework.Game.SourceGenerators.Config;
using Microsoft.CodeAnalysis.CSharp;
namespace GFramework.SourceGenerators.Tests.Config; namespace GFramework.SourceGenerators.Tests.Config;

View File

@ -1,5 +1,5 @@
using System.Reflection; using System.Reflection;
using GFramework.SourceGenerators.Cqrs; using GFramework.Cqrs.SourceGenerators.Cqrs;
using GFramework.SourceGenerators.Tests.Core; using GFramework.SourceGenerators.Tests.Core;
namespace GFramework.SourceGenerators.Tests.Cqrs; namespace GFramework.SourceGenerators.Tests.Cqrs;
@ -252,6 +252,84 @@ public class CqrsHandlerRegistryGeneratorTests
"""; """;
private const string ExternalAssemblyPreciseLookupExpected = """
// <auto-generated />
#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<Dep.VisibilityScope.ProtectedRequest, Dep.VisibilityScope.ProtectedResponse[]>.");
}
global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient(
services,
typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<global::Dep.VisibleRequest, string>),
implementationType0);
logger.Debug("Registered CQRS handler TestApp.DerivedHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<Dep.VisibleRequest, string>.");
}
}
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;
}
}
}
""";
/// <summary> /// <summary>
/// 验证生成器会为当前程序集中的 request、notification 和 stream 处理器生成稳定顺序的注册器。 /// 验证生成器会为当前程序集中的 request、notification 和 stream 处理器生成稳定顺序的注册器。
/// </summary> /// </summary>
@ -923,37 +1001,9 @@ public class CqrsHandlerRegistryGeneratorTests
contractsReference, contractsReference,
dependencyReference); dependencyReference);
Assert.Multiple(() => Assert.That(
{ generatedSource,
Assert.That( Is.EqualTo(ExternalAssemblyPreciseLookupExpected));
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<global::Dep.VisibleRequest, string>)"));
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:"));
});
} }
/// <summary> /// <summary>

View File

@ -1,7 +1,6 @@
using System.IO; using System.IO;
using GFramework.SourceGenerators.Enums; using GFramework.Core.SourceGenerators.Enums;
using GFramework.SourceGenerators.Tests.Core; using GFramework.SourceGenerators.Tests.Core;
using NUnit.Framework;
namespace GFramework.SourceGenerators.Tests.Enums; namespace GFramework.SourceGenerators.Tests.Enums;

View File

@ -1,7 +1,6 @@
using System.IO; using System.IO;
using GFramework.SourceGenerators.Logging; using GFramework.Core.SourceGenerators.Logging;
using GFramework.SourceGenerators.Tests.Core; using GFramework.SourceGenerators.Tests.Core;
using NUnit.Framework;
namespace GFramework.SourceGenerators.Tests.Logging; namespace GFramework.SourceGenerators.Tests.Logging;

View File

@ -1,7 +1,6 @@
using System.IO; using System.IO;
using GFramework.SourceGenerators.Rule; using GFramework.Core.SourceGenerators.Rule;
using GFramework.SourceGenerators.Tests.Core; using GFramework.SourceGenerators.Tests.Core;
using NUnit.Framework;
namespace GFramework.SourceGenerators.Tests.Rule; namespace GFramework.SourceGenerators.Tests.Rule;

View File

@ -1,4 +1,4 @@
using GFramework.SourceGenerators.Rule; using GFramework.Core.SourceGenerators.Rule;
using GFramework.SourceGenerators.Tests.Core; using GFramework.SourceGenerators.Tests.Core;
namespace GFramework.SourceGenerators.Tests.Rule; namespace GFramework.SourceGenerators.Tests.Rule;

View File

@ -30,19 +30,18 @@
<None Remove="GFramework.Game\**"/> <None Remove="GFramework.Game\**"/>
<None Remove="GFramework.Godot\**"/> <None Remove="GFramework.Godot\**"/>
<None Update="GFramework.Core.SourceGenerators\logging\README.md"> <None Update="GFramework.Core.SourceGenerators\logging\README.md">
<Link>GFramework.SorceGenerators\logging\README.md</Link> <Link>GFramework.Core.SourceGenerators\logging\README.md</Link>
</None> </None>
<None Update="GFramework.Core.SourceGenerators\README.md"> <None Update="GFramework.Core.SourceGenerators\README.md">
<Link>GFramework.SorceGenerators\README.md</Link> <Link>GFramework.Core.SourceGenerators\README.md</Link>
</None> </None>
<None Update="GFramework.Core.SourceGenerators\AnalyzerReleases.Shipped.md"> <None Update="GFramework.Core.SourceGenerators\AnalyzerReleases.Shipped.md">
<Link>GFramework.SorceGenerators\AnalyzerReleases.Shipped.md</Link> <Link>GFramework.Core.SourceGenerators\AnalyzerReleases.Shipped.md</Link>
</None> </None>
<None Update="GFramework.Core.SourceGenerators\AnalyzerReleases.Unshipped.md"> <None Update="GFramework.Core.SourceGenerators\AnalyzerReleases.Unshipped.md">
<Link>GFramework.SorceGenerators\AnalyzerReleases.Unshipped.md</Link> <Link>GFramework.Core.SourceGenerators\AnalyzerReleases.Unshipped.md</Link>
</None> </None>
<None Remove="GFramework.Godot.SourceGenerators\**"/> <None Remove="GFramework.Godot.SourceGenerators\**"/>
<None Remove="GFramework.SorceGenerators\**"/>
<None Remove="GFramework.SourceGenerators\**"/> <None Remove="GFramework.SourceGenerators\**"/>
<None Remove="GFramework.Core.SourceGenerators\**"/> <None Remove="GFramework.Core.SourceGenerators\**"/>
<None Remove="GFramework.Core.SourceGenerators.Abstractions\**"/> <None Remove="GFramework.Core.SourceGenerators.Abstractions\**"/>
@ -82,16 +81,15 @@
<Compile Remove="GFramework.Game\**"/> <Compile Remove="GFramework.Game\**"/>
<Compile Remove="GFramework.Godot\**"/> <Compile Remove="GFramework.Godot\**"/>
<Compile Update="GFramework.Core.SourceGenerators\enums\EnumExtensionsGenerator.cs"> <Compile Update="GFramework.Core.SourceGenerators\enums\EnumExtensionsGenerator.cs">
<Link>GFramework.SorceGenerators\enums\EnumExtensionsGenerator.cs</Link> <Link>GFramework.Core.SourceGenerators\enums\EnumExtensionsGenerator.cs</Link>
</Compile> </Compile>
<Compile Update="GFramework.Core.SourceGenerators\logging\Diagnostic.cs"> <Compile Update="GFramework.Core.SourceGenerators\logging\Diagnostic.cs">
<Link>GFramework.SorceGenerators\logging\Diagnostic.cs</Link> <Link>GFramework.Core.SourceGenerators\logging\Diagnostic.cs</Link>
</Compile> </Compile>
<Compile Update="GFramework.Core.SourceGenerators\logging\LoggerGenerator.cs"> <Compile Update="GFramework.Core.SourceGenerators\logging\LoggerGenerator.cs">
<Link>GFramework.SorceGenerators\logging\LoggerGenerator.cs</Link> <Link>GFramework.Core.SourceGenerators\logging\LoggerGenerator.cs</Link>
</Compile> </Compile>
<Compile Remove="GFramework.Godot.SourceGenerators\**"/> <Compile Remove="GFramework.Godot.SourceGenerators\**"/>
<Compile Remove="GFramework.SorceGenerators\**"/>
<Compile Remove="GFramework.SourceGenerators\**"/> <Compile Remove="GFramework.SourceGenerators\**"/>
<Compile Remove="GFramework.Core.SourceGenerators\**"/> <Compile Remove="GFramework.Core.SourceGenerators\**"/>
<Compile Remove="GFramework.Core.SourceGenerators.Abstractions\**"/> <Compile Remove="GFramework.Core.SourceGenerators.Abstractions\**"/>
@ -126,7 +124,6 @@
<EmbeddedResource Remove="GFramework.Game\**"/> <EmbeddedResource Remove="GFramework.Game\**"/>
<EmbeddedResource Remove="GFramework.Godot\**"/> <EmbeddedResource Remove="GFramework.Godot\**"/>
<EmbeddedResource Remove="GFramework.Godot.SourceGenerators\**"/> <EmbeddedResource Remove="GFramework.Godot.SourceGenerators\**"/>
<EmbeddedResource Remove="GFramework.SorceGenerators\**"/>
<EmbeddedResource Remove="GFramework.SourceGenerators\**"/> <EmbeddedResource Remove="GFramework.SourceGenerators\**"/>
<EmbeddedResource Remove="GFramework.Core.SourceGenerators\**"/> <EmbeddedResource Remove="GFramework.Core.SourceGenerators\**"/>
<EmbeddedResource Remove="GFramework.Core.SourceGenerators.Abstractions\**"/> <EmbeddedResource Remove="GFramework.Core.SourceGenerators.Abstractions\**"/>

View File

@ -68,8 +68,11 @@ dotnet add package GeWuYou.GFramework.Game.Abstractions
# Godot 集成(仅 Godot 项目需要) # Godot 集成(仅 Godot 项目需要)
dotnet add package GeWuYou.GFramework.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
``` ```
## 可选模块导入 ## 可选模块导入

View File

@ -247,6 +247,8 @@ public class GameArchitecture : Architecture
handler。 handler。
`RegisterCqrsPipelineBehavior<TBehavior>()` 是唯一保留的公开入口;旧的 `Mediator` 兼容别名与扩展已移除,不再继续维护。 `RegisterCqrsPipelineBehavior<TBehavior>()` 是唯一保留的公开入口;旧的 `Mediator` 兼容别名与扩展已移除,不再继续维护。
如果你正在从旧版本迁移,显式替换关系就是
`RegisterMediatorBehavior<TBehavior>() -> RegisterCqrsPipelineBehavior<TBehavior>()`
当前接口支持两种形式: 当前接口支持两种形式:
- 开放泛型行为,例如 `LoggingBehavior<,>`,用于匹配所有请求 - 开放泛型行为,例如 `LoggingBehavior<,>`,用于匹配所有请求

View File

@ -180,7 +180,9 @@ GameProject/
如果你使用打包后的 NuGet而不是仓库内项目引用原则保持不变 如果你使用打包后的 NuGet而不是仓库内项目引用原则保持不变
- 运行时项目需要引用 `GeWuYou.GFramework.Game` - 运行时项目需要引用 `GeWuYou.GFramework.Game`
- 生成器项目需要引用 `GeWuYou.GFramework.SourceGenerators` - 配置 schema 生成器需要引用 `GeWuYou.GFramework.Game.SourceGenerators`
- 如果同一项目还会使用 `[Log]``[ContextAware]``[GetSystem]` 等 Core 侧生成器特性,再额外引用
`GeWuYou.GFramework.Core.SourceGenerators`
- schema 目录默认仍然是 `schemas/` - schema 目录默认仍然是 `schemas/`
如果你的 schema 不放在默认目录,可以在项目文件里覆盖: 如果你的 schema 不放在默认目录,可以在项目文件里覆盖:

View File

@ -6,13 +6,18 @@ GFramework 提供多种安装方式,您可以根据项目需求选择合适的
GFramework 采用模块化设计,不同包提供不同的功能: GFramework 采用模块化设计,不同包提供不同的功能:
| 包名 | 说明 | 适用场景 | | 包名 | 说明 | 适用场景 |
|---------------------------------------|---------|-----------| |---------------------------------------------|-------------|--------------------------------|
| `GeWuYou.GFramework` | 聚合元包 | 快速试用、原型开发 | | `GeWuYou.GFramework` | 聚合元包 | 快速试用、原型开发 |
| `GeWuYou.GFramework.Core` | 核心框架 | 生产项目推荐 | | `GeWuYou.GFramework.Core` | 核心框架 | 生产项目推荐 |
| `GeWuYou.GFramework.Game` | 游戏模块 | 需要游戏特定功能 | | `GeWuYou.GFramework.Game` | 游戏模块 | 需要游戏特定功能 |
| `GeWuYou.GFramework.Godot` | Godot集成 | Godot项目必需 | | `GeWuYou.GFramework.Godot` | Godot集成 | Godot项目必需 |
| `GeWuYou.GFramework.SourceGenerators` | 源码生成器 | 推荐安装 | | `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 项目需要) # Godot 集成(仅 Godot 项目需要)
dotnet add package GeWuYou.GFramework.Godot dotnet add package GeWuYou.GFramework.Godot
# 源码生成器(可选,但推荐) # Core 侧源码生成器([Log] / [ContextAware] / [GetSystem] 等)
dotnet add package GeWuYou.GFramework.SourceGenerators 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 ### 2. 使用 PackageReference
@ -56,8 +70,14 @@ dotnet add package GeWuYou.GFramework.SourceGenerators
<!-- Godot 集成 --> <!-- Godot 集成 -->
<PackageReference Include="GeWuYou.GFramework.Godot" Version="1.0.0" /> <PackageReference Include="GeWuYou.GFramework.Godot" Version="1.0.0" />
<!-- 源码生成器 --> <!-- 按场景选择的源码生成器 -->
<PackageReference Include="GeWuYou.GFramework.SourceGenerators" Version="1.0.0" <PackageReference Include="GeWuYou.GFramework.Core.SourceGenerators" Version="1.0.0"
PrivateAssets="all" ExcludeAssets="runtime" />
<PackageReference Include="GeWuYou.GFramework.Game.SourceGenerators" Version="1.0.0"
PrivateAssets="all" ExcludeAssets="runtime" />
<PackageReference Include="GeWuYou.GFramework.Godot.SourceGenerators" Version="1.0.0"
PrivateAssets="all" ExcludeAssets="runtime" />
<PackageReference Include="GeWuYou.GFramework.Cqrs.SourceGenerators" Version="1.0.0"
PrivateAssets="all" ExcludeAssets="runtime" /> PrivateAssets="all" ExcludeAssets="runtime" />
</ItemGroup> </ItemGroup>
</Project> </Project>
@ -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 - 重启 IDE
- 清理并重新构建项目 - 清理并重新构建项目

View File

@ -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 包安装 ### NuGet 包安装
```xml ```xml
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="GeWuYou.GFramework.SourceGenerators" Version="1.0.0"/> <PackageReference Include="GeWuYou.GFramework.Core.SourceGenerators" Version="1.0.0"
<PackageReference Include="GeWuYou.GFramework.SourceGenerators.Attributes" Version="1.0.0"/> PrivateAssets="all"
ExcludeAssets="runtime" />
<PackageReference Include="GeWuYou.GFramework.Game.SourceGenerators" Version="1.0.0"
PrivateAssets="all"
ExcludeAssets="runtime" />
</ItemGroup> </ItemGroup>
</Project> </Project>
``` ```
如果你只使用 Godot 生成器或 CQRS 处理器注册生成器,请把上面的包替换为对应的
`GeWuYou.GFramework.Godot.SourceGenerators``GeWuYou.GFramework.Cqrs.SourceGenerators`
这些拆分包会同时带上各自需要的 abstractions 程序集,不需要再额外安装单独的 `*.Attributes` 包。
### Config Schema 文件约定 ### Config Schema 文件约定
当项目引用 `GeWuYou.GFramework.SourceGenerators` 的打包产物时,生成器会默认从 `schemas/**/*.schema.json` 收集配置 schema 当项目引用 `GeWuYou.GFramework.Game.SourceGenerators` 的打包产物时,生成器会默认从 `schemas/**/*.schema.json` 收集配置
schema
文件并作为 `AdditionalFiles` 输入。 文件并作为 `AdditionalFiles` 输入。
这意味着消费者项目通常只需要维护如下结构: 这意味着消费者项目通常只需要维护如下结构:
@ -150,7 +167,7 @@ Config Schema 生成器会扫描 `*.schema.json` 文件,并生成:
### 基础使用 ### 基础使用
```csharp ```csharp
using GFramework.SourceGenerators.Attributes; using GFramework.SourceGenerators.Abstractions.Logging;
[Log] [Log]
public partial class PlayerController public partial class PlayerController

View File

@ -74,8 +74,11 @@ dotnet add package GeWuYou.GFramework
# Godot 集成 # Godot 集成
dotnet add package GeWuYou.GFramework.Godot dotnet add package GeWuYou.GFramework.Godot
# 源码生成器(可选,但推荐) # Core 侧源码生成器([Log] / [ContextAware] 等)
dotnet add package GeWuYou.GFramework.SourceGenerators dotnet add package GeWuYou.GFramework.Core.SourceGenerators
# Godot 侧源码生成器([GetNode] / [AutoUiPage] 等)
dotnet add package GeWuYou.GFramework.Godot.SourceGenerators
``` ```
::: details 分包安装(了解即可) ::: details 分包安装(了解即可)
@ -93,8 +96,11 @@ dotnet add package GeWuYou.GFramework.Game.Abstractions
# Godot 集成 # Godot 集成
dotnet add package GeWuYou.GFramework.Godot dotnet add package GeWuYou.GFramework.Godot
# 源码生成器 # Core 侧源码生成器
dotnet add package GeWuYou.GFramework.SourceGenerators 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. 安装以下包: 3. 安装以下包:
- `GeWuYou.GFramework` - `GeWuYou.GFramework`
- `GeWuYou.GFramework.Godot` - `GeWuYou.GFramework.Godot`
- `GeWuYou.GFramework.SourceGenerators` - `GeWuYou.GFramework.Core.SourceGenerators`
- `GeWuYou.GFramework.Godot.SourceGenerators`
![NuGet 包管理](../assets/basic/image-20260211211756993.png) ![NuGet 包管理](../assets/basic/image-20260211211756993.png)