Appearance
术语分册 1:入口与输出
这一册只回答一个问题:一个最小增量生成器从哪里开始,以及源码最终是怎么被加进编译的。
[Generator]
- 一句话说明:把一个类标记为源生成器
- 什么时候会用到:每个生成器类声明上
- 当前仓库位置:
sample/01-tostring-generator/ToStringGenerator/ToStringGenerator.cs
关键点:
| 你需要知道什么 | 说明 |
|---|---|
| 它解决什么问题 | 让编译器识别这个类是生成器 |
| 只有接口够不够 | 通常不够,仍然应该加 [Generator] |
| 它是不是运行时特性 | 不是,它服务的是编译期发现 |
IIncrementalGenerator
- 一句话说明:增量源生成器的入口接口
- 什么时候会用到:你实现生成器时
- 对应教程:第 4 章
关键成员:
| 成员 | 能拿到什么 | 当前仓库怎么用 |
|---|---|---|
Initialize(IncrementalGeneratorInitializationContext context) | 初始化上下文 | 注册固定输出和动态输出 |
最实用的理解:
- 这不是运行时接口
- 这不是给业务代码直接调用的接口
- 它的职责是在编译期“搭管道”
IncrementalGeneratorInitializationContext
关键成员:
| 成员 | 能拿到什么 | 当前仓库怎么用 |
|---|---|---|
SyntaxProvider | 语法筛选入口 | 找带特性的类 |
CompilationProvider | 整个编译对象 | 高级生成器里常与 Combine(...) 一起用 |
AdditionalTextsProvider | 附加文件输入 | sample/09 读取 .graphql 文件 |
AnalyzerConfigOptionsProvider | 配置与构建属性输入 | 用于读取全局或文件级配置 |
RegisterPostInitializationOutput(...) | 注册固定输出 | 生成 GenerateToStringAttribute |
RegisterSourceOutput(...) | 把分析结果接到最终输出 | 输出 ToString() 代码 |
常见误解:
- 它不是“当前类信息容器”
- 它更像“初始化阶段的控制台”
RegisterPostInitializationOutput(...)
- 一句话说明:注册不依赖用户代码的固定输出
- 什么时候会用到:生成特性、固定帮助类、固定常量文件
- 对应教程:第 5 章
重点理解:
| 关注点 | 说明 |
|---|---|
| 是否依赖用户类 | 否 |
| 适合生成什么 | 特性、固定帮助类 |
| 当前仓库用途 | 生成 GenerateToStringAttribute.g.cs |
SourceProductionContext
关键成员:
| 成员 | 能拿到什么 | 当前仓库怎么用 |
|---|---|---|
AddSource(...) | 把源码加入编译 | 输出 .g.cs |
ReportDiagnostic(...) | 上报错误、警告、提示 | 主案例未直接用,扩展样例会用 |
CancellationToken | 当前阶段的取消令牌 | 长流程里应该尊重它 |
AddSource(...)
常见重载:
| 重载 | 说明 |
|---|---|
AddSource(string hintName, string source) | 直接传字符串源码 |
AddSource(string hintName, SourceText sourceText) | 传带编码信息的源码文本 |
参数含义:
| 参数 | 作用 |
|---|---|
hintName | 生成文件提示名,应稳定且尽量唯一 |
source / sourceText | 生成的源码内容 |
常见误解:
- 它不是在项目目录里创建物理文件
- 它是把源码塞进“这次编译的输入”
RegisterSourceOutput(...)
关键理解:
| 你现在关心什么 | 说明 |
|---|---|
| 第一个参数是什么 | 上游 provider 产出的值 |
| 第二个参数是什么 | 输出回调,常见签名是 (spc, value) => ... |
| 当前仓库怎么用 | 把 ClassToGenerate 交给 GenerateToStringCode(...) |
最常见的最小链路
csharp
[Generator]
public sealed class DemoGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.RegisterPostInitializationOutput(static ctx =>
{
ctx.AddSource("DemoAttribute.g.cs", "internal sealed class DemoAttribute : Attribute {}");
});
}
}下一步去哪里
- 想理解特性筛选、语法与语义:看 术语分册 2:语法与语义
- 想理解类、属性、类型对象:看 术语分册 3:符号与类型
- 返回索引:看 术语与 API 手册