Skip to content

术语分册 1:入口与输出

这一册只回答一个问题:一个最小增量生成器从哪里开始,以及源码最终是怎么被加进编译的。

[Generator]

  • 一句话说明:把一个类标记为源生成器
  • 什么时候会用到:每个生成器类声明上
  • 当前仓库位置:sample/01-tostring-generator/ToStringGenerator/ToStringGenerator.cs

关键点:

你需要知道什么说明
它解决什么问题让编译器识别这个类是生成器
只有接口够不够通常不够,仍然应该加 [Generator]
它是不是运行时特性不是,它服务的是编译期发现

IIncrementalGenerator

  • 一句话说明:增量源生成器的入口接口
  • 什么时候会用到:你实现生成器时
  • 对应教程:第 4 章

关键成员:

成员能拿到什么当前仓库怎么用
Initialize(IncrementalGeneratorInitializationContext context)初始化上下文注册固定输出和动态输出

最实用的理解:

  • 这不是运行时接口
  • 这不是给业务代码直接调用的接口
  • 它的职责是在编译期“搭管道”

IncrementalGeneratorInitializationContext

  • 一句话说明:在 Initialize(...) 里搭建增量处理管道的上下文对象
  • 什么时候会用到:一进入 Initialize(...) 就会用到
  • 对应教程:第 4 章第 5 章

关键成员:

成员能拿到什么当前仓库怎么用
SyntaxProvider语法筛选入口找带特性的类
CompilationProvider整个编译对象高级生成器里常与 Combine(...) 一起用
AdditionalTextsProvider附加文件输入sample/09 读取 .graphql 文件
AnalyzerConfigOptionsProvider配置与构建属性输入用于读取全局或文件级配置
RegisterPostInitializationOutput(...)注册固定输出生成 GenerateToStringAttribute
RegisterSourceOutput(...)把分析结果接到最终输出输出 ToString() 代码

常见误解:

  • 它不是“当前类信息容器”
  • 它更像“初始化阶段的控制台”

RegisterPostInitializationOutput(...)

  • 一句话说明:注册不依赖用户代码的固定输出
  • 什么时候会用到:生成特性、固定帮助类、固定常量文件
  • 对应教程:第 5 章

重点理解:

关注点说明
是否依赖用户类
适合生成什么特性、固定帮助类
当前仓库用途生成 GenerateToStringAttribute.g.cs

SourceProductionContext

  • 一句话说明:最终输出阶段使用的上下文对象
  • 什么时候会用到:进入 RegisterSourceOutput(...) 的回调以后
  • 对应教程:第 9 章第 11 章

关键成员:

成员能拿到什么当前仓库怎么用
AddSource(...)把源码加入编译输出 .g.cs
ReportDiagnostic(...)上报错误、警告、提示主案例未直接用,扩展样例会用
CancellationToken当前阶段的取消令牌长流程里应该尊重它

AddSource(...)

  • 一句话说明:把一段源码加入当前编译
  • 什么时候会用到:固定输出和动态输出都会用
  • 对应教程:第 5 章第 11 章

常见重载:

重载说明
AddSource(string hintName, string source)直接传字符串源码
AddSource(string hintName, SourceText sourceText)传带编码信息的源码文本

参数含义:

参数作用
hintName生成文件提示名,应稳定且尽量唯一
source / sourceText生成的源码内容

常见误解:

  • 它不是在项目目录里创建物理文件
  • 它是把源码塞进“这次编译的输入”

RegisterSourceOutput(...)

  • 一句话说明:把前面 provider 的结果连接到最终输出动作
  • 什么时候会用到:你已经筛到了目标、提取了信息,现在要真正生成源码
  • 对应教程:第 9 章第 11 章

关键理解:

你现在关心什么说明
第一个参数是什么上游 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 {}");
        });
    }
}

下一步去哪里

基于当前仓库文档副本构建的 VitePress 站点