Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions docs/zh-CN/api-reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -440,11 +440,28 @@ Godot 引擎集成模块。

#### 支持的生成器

| 生成器 | 说明 |
|--------------------|---------|
| `LoggingGenerator` | 日志生成器 |
| `EnumGenerator` | 枚举扩展生成器 |
| `RuleGenerator` | 规则生成器 |
| 生成器 | 说明 |
|--------------------------------------------|-------------|
| `LoggingGenerator` | 日志生成器 |
| `EnumGenerator` | 枚举扩展生成器 |
| `RuleGenerator` | 规则生成器 |
| `AutoRegisterModuleGenerator` | 架构模块注册生成器 |
| `AutoUiPageGenerator` | UI 页面行为生成器 |
| `AutoSceneGenerator` | 场景行为生成器 |
| `AutoRegisterExportedCollectionsGenerator` | 导出集合批量注册生成器 |

#### 常用 Attribute

| Attribute | 说明 | 文档 |
|--------------------------------------------|-----------------------------------|-------------------------------------------------------------------------------------------------------------|
| `AutoRegisterModuleAttribute` | 为模块类生成 `Install(IArchitecture)` | [AutoRegisterModule 生成器](../source-generators/auto-register-module-generator.md) |
| `RegisterModelAttribute` | 声明模块内自动注册的 `IModel` 类型 | [AutoRegisterModule 生成器](../source-generators/auto-register-module-generator.md) |
| `RegisterSystemAttribute` | 声明模块内自动注册的 `ISystem` 类型 | [AutoRegisterModule 生成器](../source-generators/auto-register-module-generator.md) |
| `RegisterUtilityAttribute` | 声明模块内自动注册的 `IUtility` 类型 | [AutoRegisterModule 生成器](../source-generators/auto-register-module-generator.md) |
| `AutoUiPageAttribute` | 为 `CanvasItem` 页面节点生成 `GetPage()` | [AutoUiPage 生成器](../source-generators/auto-ui-page-generator.md) |
| `AutoSceneAttribute` | 为场景根节点生成 `GetScene()` | [AutoScene 生成器](../source-generators/auto-scene-generator.md) |
| `AutoRegisterExportedCollectionsAttribute` | 为宿主类开启导出集合批量注册生成 | [AutoRegisterExportedCollections 生成器](../source-generators/auto-register-exported-collections-generator.md) |
| `RegisterExportedCollectionAttribute` | 指定集合与注册器成员的映射关系 | [AutoRegisterExportedCollections 生成器](../source-generators/auto-register-exported-collections-generator.md) |

## 常见用法示例

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# AutoRegisterExportedCollections 生成器

> 为 Godot 导出集合生成批量注册方法,收敛启动入口里的重复 `foreach + Registry(...)` 样板。

## 概述

在游戏启动入口中,常见的一类样板是:

- 在 Inspector 中导出一批配置、资源映射或预制体条目
- 从某个 Registry 成员拿到注册器
- 遍历集合逐项调用 `Register(...)` / `Registry(...)`

`AutoRegisterExportedCollections` 会把这类样板收敛成声明式配置。

它特别适合 `GameEntryPoint`、资源根节点、配置引导节点这类“导出即注册”的场景。

## 基础使用

```csharp
using System.Collections.Generic;
using GFramework.Godot.SourceGenerators.Abstractions;
using Godot;

public interface IKeyValue<TKey, TValue>
{
}

public interface IRegistry<TKey, TValue>
{
void Registry(IKeyValue<TKey, TValue> mapping);
}

public interface IAssetRegistry<TValue> : IRegistry<string, TValue>
{
}

public sealed class TextureConfig : Resource, IKeyValue<string, Texture2D>
{
}

public sealed class TextureRegistry : IAssetRegistry<Texture2D>
{
public void Registry(IKeyValue<string, Texture2D> mapping)
{
}
}

[AutoRegisterExportedCollections]
public partial class GameEntryPoint : Node
{
private IAssetRegistry<Texture2D>? _textureRegistry;

[Export]
[RegisterExportedCollection(nameof(_textureRegistry), nameof(IRegistry<string, Texture2D>.Registry))]
private Godot.Collections.Array<TextureConfig>? _textureConfigs;

public override void _Ready()
Comment thread
GeWuYou marked this conversation as resolved.
{
_textureRegistry ??= new TextureRegistry();
__RegisterExportedCollections_Generated();
}
}
```

为了让示例具备完整的调用路径,这里在 `_Ready()` 里先初始化了 `_textureRegistry`。
实际项目里,这个字段通常来自架构容器、服务定位或外部注入;关键点是调用 `__RegisterExportedCollections_Generated()`
之前,注册器成员必须已经可用,否则生成代码会按设计静默跳过注册。

## 生成的代码

```csharp
// <auto-generated />
#nullable enable

partial class GameEntryPoint
{
private void __RegisterExportedCollections_Generated()
{
if (this._textureConfigs is not null && this._textureRegistry is not null)
{
foreach (var __generatedItem in this._textureConfigs)
{
this._textureRegistry.Registry(__generatedItem);
}
}
}
}
```

## 参数说明

### `[AutoRegisterExportedCollections]`

类级标记,声明该类型允许生成 `__RegisterExportedCollections_Generated()`。

### `[RegisterExportedCollection(registryMemberName, registerMethodName)]`

| 参数 | 类型 | 说明 |
|----------------------|----------|----------------------------------|
| `registryMemberName` | `string` | 当前类型上用于执行注册的字段或属性名 |
| `registerMethodName` | `string` | 注册方法名,例如 `Register` 或 `Registry` |

推荐优先使用 `nameof(...)` 表达式,而不是手写字符串。

## 支持的匹配规则

生成器会在编译期验证:

- 集合成员必须是实例字段,或可读的实例属性
- 集合类型必须可枚举
- 集合元素类型必须能在编译期推导
- 注册器成员必须是实例字段,或可读的实例属性
- 注册方法必须是单参数实例方法,且参数类型能接收集合元素类型

当前版本还支持从以下位置解析注册方法:

- 注册器具体类型本身
- 注册器基类
- 注册器实现的接口
- 继承链上的接口

这意味着像 `IAssetRegistry<T>` 继承 `IRegistry<TKey, TValue>` 的项目结构也能正常生成,不必再把注册器字段改成具体实现类型。

## 适用场景

推荐用于:

- `GameEntryPoint` 中的资源注册
- 场景启动时的配置条目注册
- Inspector 预配置的纹理、音频、Prefab、场景映射批量接入

不推荐用于:

- 注册前需要复杂过滤、去重、排序、条件判断的集合
- 需要记录失败项、错误聚合或回滚逻辑的批量导入
- 每个元素注册时都依赖额外上下文或副作用控制的流程

## 使用约束

- 目标类型必须是 `partial class`
- 不支持嵌套类
- 生成器不会自动调用 `__RegisterExportedCollections_Generated()`
- 非泛型 `IEnumerable` 之类无法推导元素类型的集合不受支持
- 注册方法必须对宿主类型可访问

## 诊断信息

| 诊断 ID | 含义 |
|-----------------------|-------------------------------------------------------------|
| `GF_Common_Class_001` | 目标类型不是 `partial`,生成被跳过 |
| `GF_Common_Class_002` | 宿主类型已声明 `__RegisterExportedCollections_Generated()`,与生成代码冲突 |
| `GF_AutoExport_001` | `AutoRegisterExportedCollections` 不支持嵌套类 |
| `GF_AutoExport_002` | 指定的注册器成员不存在 |
| `GF_AutoExport_003` | 注册器成员上找不到兼容的注册方法 |
| `GF_AutoExport_004` | 被标记的成员不是可枚举集合 |
| `GF_AutoExport_005` | 无法推导集合元素类型 |
| `GF_AutoExport_006` | 集合成员不是实例可读成员 |
| `GF_AutoExport_007` | 注册器成员不是实例可读成员 |
| `GF_AutoExport_008` | `RegisterExportedCollectionAttribute` 参数无效 |

## 调用时机建议

推荐在以下时机之一调用生成方法:

- `_Ready()` 中,且在注册器字段已经准备好之后
- 启动入口的显式 `Initialize()` 或 `Bootstrap()` 方法中
- 测试中的装配阶段

不要在构造函数中调用,因为此时 Godot 导出字段和外部依赖通常还未准备完毕。

## 相关文档

- [源码生成器总览](./index)
- [游戏内容配置系统](/zh-CN/game/config-system)
153 changes: 153 additions & 0 deletions docs/zh-CN/source-generators/auto-register-module-generator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# AutoRegisterModule 生成器

> 为架构模块生成固定顺序的组件注册代码,收敛 `Install(IArchitecture)` 样板。

## 概述

`AutoRegisterModule` 面向 GFramework 的模块安装场景。
当一个模块类只需要按固定顺序注册若干 `Model`、`System`、`Utility` 时,开发者不必再手写重复的 `Install(IArchitecture)` 方法。

生成器会扫描类上的:

- `[AutoRegisterModule]`
- `[RegisterModel(typeof(...))]`
- `[RegisterSystem(typeof(...))]`
- `[RegisterUtility(typeof(...))]`

然后在编译期生成统一的安装方法。

### 核心收益

- 把模块注册入口收敛到声明式 Attribute
- 避免漏注册、顺序漂移和重复样板
- 保持零运行时反射开销

## 基础使用

```csharp
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
using GFramework.SourceGenerators.Abstractions.Architectures;

public sealed class RunStateModel : IModel
{
}

public sealed class BuildSystem : ISystem
{
}

public sealed class GridPathUtility : IUtility
{
}

[AutoRegisterModule]
[RegisterModel(typeof(RunStateModel))]
[RegisterSystem(typeof(BuildSystem))]
[RegisterUtility(typeof(GridPathUtility))]
public partial class GameplayModule
{
}
```

## 生成的代码

编译器会生成与下述结构等价的代码:

```csharp
// <auto-generated />
#nullable enable

partial class GameplayModule
{
public void Install(global::GFramework.Core.Abstractions.Architectures.IArchitecture architecture)
{
architecture.RegisterModel(new global::RunStateModel());
architecture.RegisterSystem(new global::BuildSystem());
architecture.RegisterUtility(new global::GridPathUtility());
}
}
```

## 参数说明

### `[AutoRegisterModule]`

类级标记,用于声明该类型允许生成 `Install(IArchitecture)`。

### `[RegisterModel(typeof(TModel))]`

| 参数 | 类型 | 说明 |
|-------------|--------|--------------------|
| `modelType` | `Type` | 要注册的 `IModel` 实现类型 |

### `[RegisterSystem(typeof(TSystem))]`

| 参数 | 类型 | 说明 |
|--------------|--------|---------------------|
| `systemType` | `Type` | 要注册的 `ISystem` 实现类型 |

### `[RegisterUtility(typeof(TUtility))]`

| 参数 | 类型 | 说明 |
|---------------|--------|----------------------|
| `utilityType` | `Type` | 要注册的 `IUtility` 实现类型 |

## 顺序规则

生成器会按 Attribute 的稳定声明顺序输出注册语句。

- 同一个 `partial` 声明内:按源码书写顺序生成
- 多个 `partial` 文件之间:按语法树稳定顺序合并

这意味着模块安装顺序是可预期的,适合游戏启动时需要确定初始化顺序的场景。

## 适用场景

推荐用于:

- 游戏主架构中的固定模块安装
- 菜单模块、战斗模块、局内模块等声明式注册
- 仅依赖无参构造即可完成初始化的组件

不推荐用于:

- 需要运行时参数、配置对象或工厂参与构造的组件
- 注册前必须执行复杂前置逻辑的模块
- 注册逻辑本身存在分支、条件或环境判断的模块

## 使用约束

- 目标类型必须是 `partial class`
- 不支持嵌套类
- 目标类型上不能自己再声明 `Install(IArchitecture)`
- 注册类型必须是具体类型,不能是抽象类或接口
- 注册类型必须实现对应接口:
- `RegisterModel` 对应 `IModel`
- `RegisterSystem` 对应 `ISystem`
- `RegisterUtility` 对应 `IUtility`
- 注册类型必须存在可访问的无参构造函数

## 诊断信息

| 诊断 ID | 含义 |
|-----------------------|------------------------------------------|
| `GF_Common_Class_001` | 目标类型不是 `partial`,生成被跳过 |
| `GF_AutoModule_001` | `AutoRegisterModule` 不支持嵌套类 |
| `GF_AutoModule_002` | 注册特性没有提供有效的具体类型参数 |
| `GF_AutoModule_003` | 注册类型没有实现要求的接口 |
| `GF_AutoModule_004` | 注册类型缺少可访问的无参构造 |
| `GF_AutoModule_005` | 宿主类型已声明 `Install(IArchitecture)`,与生成代码冲突 |

## 注意事项

- 生成器只负责生成安装方法,不会自动调用它;模块仍需由你的架构启动逻辑显式执行。
- 如果某个组件需要通过 Service、配置表或 Godot 导出字段来完成构造,优先保留手写注册代码。
- 当注册逻辑已经包含较强的业务语义时,不要为了消灭几行代码而强行改成声明式生成。

## 相关文档

- [源码生成器总览](./index)
- [Context Get 注入生成器](./context-get-generator)
Loading
Loading