Source Generator 必须通过 Execute 中调用 context.AddSource() 生效,且仅 IIncrementalGenerator 被推荐;需正确配置项目引用、特性命名空间、类可见性及增量管道纯函数性,否则静默失效或破坏编译性能。

Source Generator 不是运行时魔法,也不是编译后插件——它必须在 Execute 中调用 context.AddSource() 才能生效,且生成的代码会参与完整编译流程(类型检查、补全、报错),否则就只是“写了但没生成”。
为什么 IIncrementalGenerator 是唯一推荐路径
旧式 ISourceGenerator 已被标记为过时,Roslyn 增量编译模型要求你显式声明依赖项。直接遍历 compilation.SyntaxTrees 会导致每次编译都全量执行,构建速度直线下降。
- 必须用
context.SyntaxProvider.CreateSyntaxProvider()过滤节点(比如只处理带[AutoNotify]的属性) - 后续阶段通过
context.CompilationProvider获取语义模型,避免在语法过滤阶段就调用GetSemanticModelAsync() - 最终链式调用
.Select(...).Collect().SelectMany(...).RegisterSourceOutput(...),否则增量性失效 -
Initialize方法里不能做任何耗时操作或副作用,它只负责注册管道
[Generator] 特性写错就完全不触发
这个特性不是你自己定义的类,必须来自 Microsoft.CodeAnalysis 命名空间。手误写成 MyGenerator.Attributes.Generator 或漏引用 NuGet 包,生成器会静默失效——编译不报错,也不生成代码。
- 确认项目已引用
Microsoft.CodeAnalysis.CSharp(v4.0+) - 类必须是
public,不能是static或嵌套类(Roslyn 不扫描嵌套类型) - 不要在
Execute中throw new Exception(),这会让整个编译失败;改用context.ReportDiagnostic() - 生成文件名建议带
.g.cs后缀,如"INotifyPropertyChanged.g.cs",避免和手写文件冲突
目标项目引用 generator 必须设对两个关键属性
仅加 ProjectReference 不够,Roslyn 不会把它当 Analyzer 加载。必须显式指定 OutputItemType="Analyzer" 和 ReferenceOutputAssembly="false",否则生成器 DLL 会被当作普通依赖项参与编译,导致类型重复或找不到入口。
- 目标项目的
.csproj中要这样写:<itemgroup><projectreference include="..\MyGenerator\MyGenerator.csproj" outputitemtype="Analyzer" referenceoutputassembly="false"></projectreference></itemgroup>
- generator 项目自身应设
<isanalyzer>true</isanalyzer>,并以netstandard2.0为目标框架(兼容性最佳) - 别忘了添加
System.Collections.Immutable引用(.NET 5+ 内置,旧版需手动加)
最容易被忽略的是增量管道的“断点”:一旦你在 Select 阶段做了非纯函数操作(比如读文件、访问 DateTime.Now),整个增量链就失效,Roslyn 会退回到全量模式。真正的“高级”不在生成逻辑多复杂,而在于每一步是否可缓存、可比较、可跳过。











