source generator 不会自动生效,必须满足项目配置、引用方式、类型可见性、接口实现和执行路径五者全部对齐;最常见失效原因是 roslyn 未识别生成器,根源在于宿主项目未正确声明 outputitemtype="analyzer" 和 referenceoutputassembly="false" 的 projectreference。

Source Generator 不会自动生效,哪怕 Execute 方法写得完全正确——它必须满足项目配置、引用方式、类型可见性、接口实现和执行路径五个条件全部对齐,缺一不可。最常见“没反应”的原因,是 Roslyn 根本没加载你的生成器。
为什么 Execute 方法压根没被调用
这不是代码逻辑问题,而是宿主项目未被识别为支持 analyzer 的 SDK 风格项目:
- 目标项目
.csproj必须以<project sdk="Microsoft.NET.Sdk"></project>开头(不能是Microsoft.NET.Sdk.Web等子集 SDK,除非显式导入主 SDK) -
<targetframework></targetframework>必须是net5.0或更高(如net6.0、net8.0;netstandard2.0不支持) - 引用生成器项目时,
<projectreference></projectreference>必须同时带两个属性:OutputItemType="Analyzer"和ReferenceOutputAssembly="false" - 生成器项目自身需设
<isanalyzer>true</isanalyzer>,且目标框架推荐netstandard2.0(兼容性最佳)
[Generator] 特性不生效的典型原因
这个特性不是装饰用的,它是 Roslyn 扫描生成器类的唯一入口。写错就等于没写:
- 必须来自
Microsoft.CodeAnalysis命名空间(不是你自己定义的同名类,也不是漏引用Microsoft.CodeAnalysis.CSharpNuGet 包) - 类必须是
public、非static、非嵌套(Roslyn 不扫描嵌套类型) - 不能放在
internal或private类中,也不能加sealed或abstract -
[Generator]必须直接写在类声明前,不能通过继承或泛型间接应用
用 IIncrementalGenerator 替代 ISourceGenerator 的硬性理由
ISourceGenerator 已被标记为过时,全量执行模式会让构建速度随代码量线性下降。增量模型不是可选项,是性能底线:
- 必须用
context.SyntaxProvider.CreateSyntaxProvider()过滤节点(比如只处理带[AutoNotify]的属性),而不是在Execute中遍历所有SyntaxTree - 语义模型必须通过
context.CompilationProvider获取,不能在语法过滤阶段调用GetSemanticModelAsync() - 管道链必须完整:`.Select().Collect().SelectMany().RegisterSourceOutput()`,断掉任一环都会退化为全量执行
-
Initialize方法里禁止任何耗时操作或副作用,只允许注册管道
生成的代码不参与编译或报 CS0260 错误
生成的源文件看似写进去了,但编译器不认,往往是因为违反了 C# 编译约束:
- 文件名必须以
.g.cs结尾(如"ViewModel.g.cs"),否则 IDE 可能忽略或与手写文件冲突 - 不能尝试用生成器补全
partial class的另一部分字段——C# 要求所有partial定义在同一编译单元可见,而 generator 输出是后置注入的 - 生成内容中不能引用尚未生成或尚未解析的类型(比如依赖另一个生成器输出的类,但未声明依赖顺序)
-
context.AddSource()必须传入SourceText.From(content, Encoding.UTF8),不能直接传字符串(否则编码错误可能导致中文乱码或编译失败)
最容易被忽略的一点:生成器项目引用的 Microsoft.CodeAnalysis.CSharp 版本,必须与宿主项目所用 SDK 内置的 Roslyn 版本匹配。例如 .NET 6 对应 Roslyn 4.0+,用错版本不会报错,只会静默失效。











