Source Generator 不会自动生效,因[Generator]特性是Roslyn唯一入口,若命名空间错误、缺少Microsoft.CodeAnalysis.CSharp引用、类非public或未设OutputItemType="Analyzer"等任一配置失误,均静默失效。

Source Generator 不会自动生效,哪怕代码写对了,只要项目配置、特性引用或类声明有一处错,它就完全不运行——连警告都没有。
为什么 [Generator] 特性不触发
这个特性不是装饰用的,它是 Roslyn 找到生成器的唯一入口。常见失效原因包括:
-
[Generator]来自错误命名空间,比如手写成MyGenerator.Attributes.Generator;必须是Microsoft.CodeAnalysis.Generator - 生成器项目没引用
Microsoft.CodeAnalysis.Csharp(v4.0+),或版本与 SDK 内置 Roslyn 不匹配(如 .NET 6 项目用了 v3.x) - 类不是
public,或是static、嵌套类(Roslyn 只扫描顶层 public 类) - 目标项目引用方式错误:只加
<ProjectReference>不够,必须同时设OutputItemType="Analyzer"和ReferenceOutputAssembly="false"
IIncrementalGenerator 是唯一推荐接口
旧式 ISourceGenerator 已被标记为过时,且在每次编译时全量遍历语法树,严重拖慢构建速度。增量模型强制你显式声明依赖项,避免无谓重执行。
- 必须在
Initialize中用context.SyntaxProvider.CreateSyntaxProvider()过滤节点(例如只处理带[AutoNotify]的属性),不能在过滤阶段调用GetSemanticModelAsync() - 语义分析必须放在后续管道中,通过
context.CompilationProvider获取,再链式调用.Select().Collect().SelectMany().RegisterSourceOutput() -
Initialize方法里禁止任何副作用(如 IO、日志、缓存初始化),它只负责注册管道
生成的代码怎么注入才有效
生成逻辑必须落在 Execute 或 RegisterSourceOutput 回调里,并调用 context.AddSource(),否则就是“写了但没生成”。
- 文件名建议用
.g.cs后缀(如"INotifyPropertyChange.g.cs"),避免和手写文件冲突 - 内容必须是合法 C# 语法,否则编译直接报错;不能引用尚未生成的类型(如自己生成的
partial class在同一编译单元内不可见) - 别硬编码
compilation.SyntaxTrees[0]—— 多文件项目下索引越界,应遍历compilation.SyntaxTrees或用SyntaxProvider过滤 - 出错不要
throw new Exception(),改用context.ReportDiagnostic()发送可定位的诊断信息
目标项目必须满足的最低条件
Source Generator 是编译时机制,不是运行时插件,它对项目结构极其敏感。
- 目标项目必须是 SDK 风格项目(
<Project Sdk="Microsoft.NET.Sdk">),不能是旧式.csproj -
<TargetFramework>必须为net5.0或更高(netstandard2.0不支持) - 生成器项目自身应设
<IsAnalyzer>true</IsAnalyzer>,目标框架推荐netstandard2.0(兼容性最好) - 宿主项目若用 NuGet 引用生成器,包内需包含
analyzers/dotnet/cs/xxx.dll,且PackagePath配置正确
最容易被忽略的一点:生成器类的 public 修饰符和 [Generator] 特性必须同时存在,缺一不可;而 context.AddSource() 调用位置一旦不在增量管道末端或 Execute 内,生成就会静默跳过——你不会收到任何提示,只会发现 IDE 里找不到生成的类型、补全不出现、调试也进不去。这不是 bug,是设计使然。


















