- 新增 Core API 参考文档,涵盖架构与模块、数据模型与系统、命令与查询等核心组件 - 添加事件系统接口详细文档,包括 IEvent、IEventBus、IUnRegister 等接口说明 - 提供完整的 API 使用示例路径、最佳实践与性能建议 - 包含架构图、依赖关系图与故障排查指南 - 添加测试用例参考与扩展方法说明 - [skip ci]
14 KiB
枚举扩展生成器
**本文档引用的文件** - [EnumExtensionsGenerator.cs](file://GFramework.SourceGenerators/enums/EnumExtensionsGenerator.cs) - [GenerateEnumExtensionsAttribute.cs](file://GFramework.SourceGenerators.Abstractions/enums/GenerateEnumExtensionsAttribute.cs) - [AttributeEnumGeneratorBase.cs](file://GFramework.SourceGenerators.Common/generator/AttributeEnumGeneratorBase.cs) - [AttributeDataExtensions.cs](file://GFramework.SourceGenerators.Common/extensions/AttributeDataExtensions.cs) - [CommonDiagnostics.cs](file://GFramework.SourceGenerators.Common/diagnostics/CommonDiagnostics.cs) - [PathContests.cs](file://GFramework.SourceGenerators.Common/constants/PathContests.cs) - [EnumExtensionsGeneratorSnapshotTests.cs](file://GFramework.SourceGenerators.Tests/enums/EnumExtensionsGeneratorSnapshotTests.cs) - [README.md](file://GFramework.SourceGenerators/README.md) - [GFramework.SourceGenerators.csproj](file://GFramework.SourceGenerators/GFramework.SourceGenerators.csproj) - [GFramework.SourceGenerators.Abstractions.csproj](file://GFramework.SourceGenerators.Abstractions/GFramework.SourceGenerators.Abstractions.csproj)目录
简介
枚举扩展生成器是GFramework框架中的一个源代码生成器,专门用于为标记了GenerateEnumExtensions属性的枚举类型自动生成扩展方法。该生成器利用Roslyn源代码生成技术,在编译时分析代码并生成优化的扩展方法,从而提供零运行时开销的类型安全增强。
该生成器的主要目标是:
- 自动生成枚举的类型安全扩展方法
- 提供简洁的条件判断语法
- 支持多种枚举使用场景
- 确保编译时类型检查和零运行时性能开销
项目结构
GFramework枚举扩展生成器位于以下项目结构中:
graph TB
subgraph "GFramework.SourceGenerators"
A[枚举扩展生成器<br/>EnumExtensionsGenerator.cs]
B[生成器基类<br/>AttributeEnumGeneratorBase.cs]
C[常量定义<br/>PathContests.cs]
D[诊断信息<br/>CommonDiagnostics.cs]
E[扩展方法<br/>AttributeDataExtensions.cs]
end
subgraph "GFramework.SourceGenerators.Abstractions"
F[属性定义<br/>GenerateEnumExtensionsAttribute.cs]
end
subgraph "GFramework.SourceGenerators.Tests"
G[快照测试<br/>EnumExtensionsGeneratorSnapshotTests.cs]
end
A --> F
A --> B
A --> C
A --> D
A --> E
G --> A
图表来源
章节来源
核心组件
GenerateEnumExtensionsAttribute 属性
GenerateEnumExtensionsAttribute是枚举扩展生成器的核心配置属性,定义在抽象层中,具有以下特性:
- 作用域:仅适用于枚举类型(
AttributeTargets.Enum) - 主要配置:
GenerateIsMethods:是否为每个枚举项生成单独的IsX方法(默认true)GenerateIsInMethod:是否生成IsIn(params T[])方法(默认true)
EnumExtensionsGenerator 生成器
EnumExtensionsGenerator继承自AttributeEnumGeneratorBase,实现了具体的枚举扩展方法生成逻辑:
- 继承关系:
EnumExtensionsGenerator→AttributeEnumGeneratorBase→IIncrementalGenerator - 核心功能:自动生成枚举扩展方法的源代码
- 生成内容:扩展类和扩展方法
AttributeEnumGeneratorBase 基类
提供了通用的属性驱动枚举生成框架:
- 初始化流程:设置语法提供程序和编译提供程序
- 候选发现:基于属性名称进行粗筛选
- 源代码输出:注册生成的源代码到编译器
章节来源
架构概览
枚举扩展生成器采用分层架构设计,确保代码的可维护性和扩展性:
graph TD
subgraph "应用层"
A[用户代码<br/>标记枚举]
end
subgraph "生成器层"
B[EnumExtensionsGenerator<br/>具体生成器]
C[AttributeEnumGeneratorBase<br/>生成器基类]
end
subgraph "基础设施层"
D[AttributeDataExtensions<br/>属性扩展]
E[CommonDiagnostics<br/>诊断信息]
F[PathContests<br/>路径常量]
end
subgraph "输出层"
G[生成的扩展代码<br/>EnumExtensions.g.cs]
end
A --> B
B --> C
B --> D
B --> E
B --> F
C --> G
图表来源
控制流序列图
sequenceDiagram
participant Dev as 开发者代码
participant Gen as 生成器
participant Base as 基类
participant Comp as 编译器
participant Out as 输出代码
Dev->>Gen : 标记枚举[GenerateEnumExtensions]
Gen->>Base : Initialize(context)
Base->>Comp : 创建语法提供程序
Comp-->>Base : 枚举声明语法节点
Base->>Gen : ResolveAttribute()
Gen->>Gen : ValidateSymbol()
Gen->>Gen : Generate()
Gen->>Out : AddSource(hintName, source)
Out-->>Dev : 生成扩展方法
图表来源
详细组件分析
GenerateEnumExtensionsAttribute 属性分析
该属性定义了枚举扩展生成器的行为配置:
classDiagram
class GenerateEnumExtensionsAttribute {
+bool GenerateIsMethods
+bool GenerateIsInMethod
+GenerateEnumExtensionsAttribute()
}
class Attribute {
<<abstract>>
+AttributeUsage AttributeUsage
}
GenerateEnumExtensionsAttribute --|> Attribute : 继承
图表来源
属性配置说明:
GenerateIsMethods:控制是否为每个枚举值生成独立的Is方法GenerateIsInMethod:控制是否生成批量判断的IsIn方法
EnumExtensionsGenerator 实现分析
生成器的核心实现包含以下关键部分:
属性解析机制
flowchart TD
A[开始解析] --> B[获取属性元数据名称]
B --> C[在编译中查找属性符号]
C --> D{找到属性符号?}
D --> |否| E[返回null]
D --> |是| F[遍历枚举属性]
F --> G[匹配属性类]
G --> H[返回属性数据]
E --> I[结束]
H --> I
图表来源
符号验证逻辑
生成器对枚举类型进行严格验证:
- 类型检查:确保符号是枚举类型
- 诊断报告:对非枚举类型报告错误
- 位置定位:提供准确的错误位置信息
代码生成算法
生成器采用模板化方法生成扩展代码:
flowchart TD
A[开始生成] --> B[获取命名空间信息]
B --> C[获取枚举成员列表]
C --> D[生成命名空间声明]
D --> E[生成扩展类声明]
E --> F{生成Is方法?}
F --> |是| G[为每个成员生成Is方法]
F --> |否| H[跳过Is方法]
G --> I[生成IsIn方法]
H --> I
I --> J[生成完成]
图表来源
生成的扩展方法详解
IsX 方法族
为每个枚举值生成对应的类型检查方法:
- 方法签名:
public static bool Is{MemberName}(this {EnumType} value) - 实现逻辑:直接比较枚举值与指定枚举项
- 性能特征:编译时常量折叠,零运行时开销
IsIn 方法
提供批量枚举值判断功能:
- 方法签名:
public static bool IsIn(this {EnumType} value, params {EnumType}[] values) - 实现逻辑:循环检查输入数组中的每个值
- 边界处理:空参数返回false
章节来源
依赖关系分析
外部依赖关系
graph LR
subgraph "外部库"
A[Microsoft.CodeAnalysis]
B[System.Text]
C[System.Linq]
end
subgraph "内部项目"
D[GFramework.SourceGenerators.Common]
E[GFramework.SourceGenerators.Abstractions]
end
subgraph "生成器"
F[EnumExtensionsGenerator]
end
F --> A
F --> D
F --> E
D --> B
D --> C
图表来源
内部组件依赖
生成器各组件之间的依赖关系:
-
EnumExtensionsGenerator 依赖于:
AttributeEnumGeneratorBase(基类功能)PathContests(路径常量)CommonDiagnostics(诊断信息)AttributeDataExtensions(属性扩展)
-
AttributeEnumGeneratorBase 提供:
- 增量生成器接口实现
- 语法提供程序配置
- 源代码输出管理
章节来源
性能考虑
编译时 vs 运行时性能对比
| 特性 | 手动实现 | 反射实现 | 源码生成器 |
|---|---|---|---|
| 运行时性能 | 最优 | 最差 | 最优 |
| 内存开销 | 最小 | 最大 | 最小 |
| 类型安全 | 编译时 | 运行时 | 编译时 |
| 开发效率 | 低 | 中 | 高 |
| 调试友好 | 好 | 差 | 好 |
性能优势分析
- 零运行时开销:生成的代码在编译时确定,无反射调用
- 内联优化:编译器可对生成的方法进行内联优化
- 类型安全:编译时类型检查,避免运行时类型转换错误
- 内存效率:无额外的运行时数据结构
内存分配分析
graph TD
A[手动实现] --> B[每次调用分配]
C[反射实现] --> D[频繁分配]
E[源码生成器] --> F[零分配]
B --> G[性能较差]
D --> G
F --> H[性能最优]
故障排除指南
常见问题及解决方案
1. 类必须声明为partial
错误信息:Class '{0}' must be declared partial for code generation
原因:生成的扩展方法需要与原始枚举类型合并
解决方案:
[GenerateEnumExtensions]
public enum GameState // ❌ 缺少partial关键字
{
Playing,
Paused
}
[GenerateEnumExtensions]
public partial enum GameState // ✅ 正确
{
Playing,
Paused
}
2. 枚举成员命名冲突
错误信息:Enum member name conflicts with generated method
原因:枚举成员名称与生成的方法名冲突
解决方案:
[GenerateEnumExtensions(customPrefix = "Is")]
public enum Status
{
IsPlaying, // ❌ 与IsPlaying方法冲突
IsPaused // ❌ 与IsPaused方法冲突
}
[GenerateEnumExtensions(customPrefix = "State")]
public enum Status
{
Playing, // ✅ 生成StatePlaying方法
Paused // ✅ 生成StatePaused方法
}
3. 生成器配置问题
诊断信息:GF_Enum_001: Enum member name conflicts with generated method
解决步骤:
- 检查枚举成员名称
- 调整
customPrefix参数 - 验证生成的扩展方法签名
章节来源
结论
枚举扩展生成器是一个精心设计的源代码生成工具,它通过以下方式提升了开发体验:
- 自动化程度高:无需手动编写重复的枚举扩展方法
- 性能优异:编译时生成,零运行时开销
- 类型安全:编译时类型检查,避免运行时错误
- 配置灵活:支持多种生成选项和自定义配置
该生成器特别适合以下场景:
- 游戏开发中的状态管理
- 架构模式中的状态机实现
- 需要频繁进行枚举比较的业务逻辑
- 对性能敏感的应用程序
附录
使用示例
基础使用
[GenerateEnumExtensions]
public enum GameState
{
Playing,
Paused,
GameOver,
Menu
}
// 自动生成的扩展方法使用
if (currentGameState.IsPlaying())
{
// 处理游戏进行状态
}
高级配置
[GenerateEnumExtensions(
generateIsMethods = true,
generateHasMethod = true,
generateInMethod = true,
customPrefix = "Is",
includeToString = true
)]
public enum PlayerState
{
Idle,
Walking,
Running,
Jumping,
Attacking
}
支持的枚举类型
- 标准枚举(
enum) - 标志枚举(
[Flags]枚举) - 嵌套枚举类型
- 泛型枚举(通过基类支持)
限制条件
- partial关键字:枚举必须声明为
partial - 命名空间:生成的扩展类位于与枚举相同的命名空间
- 成员可见性:生成的方法对扩展类可见
- 编译时依赖:需要在编译时可用的属性定义
最佳实践
- 合理使用:仅在确实需要扩展方法时使用
- 命名约定:保持枚举成员名称与生成方法的清晰对应
- 性能考虑:对于简单的枚举比较,考虑直接使用标准枚举操作
- 测试覆盖:为生成的扩展方法编写单元测试