示例项目
本项目包含 8 个渐进式示例,从基础到高级逐步学习源生成器。
基础示例
1. Hello World
目录: 01-HelloWorld
最简单的源生成器示例,生成一个 Hello World 类。
学习内容:
- 创建基本的源生成器
- 使用
ISourceGenerator接口 - 添加生成的源文件
2. 增量生成器
目录: 03-IncrementalGenerator
使用增量生成器 API 提高性能。
学习内容:
IIncrementalGenerator接口- 增量管道操作
- 性能优化
3. ToString 生成器
目录: 04-ToStringGenerator
自动生成 ToString 方法。
学习内容:
- 使用特性标记类
- 分析类的属性
- 生成方法代码
高级示例
4. Builder 模式生成器
目录: 05-BuilderGenerator
生成 Builder 模式代码,实现流畅接口。
学习内容:
- 生成嵌套类
- 流畅接口设计
- 复杂代码结构生成
5. 诊断和错误报告
目录: 06-Diagnostics
报告编译错误和警告,提供清晰的错误消息。
学习内容:
- 创建诊断描述符
- 报告诊断信息
- 错误位置定位
- 不同严重级别的使用
6. 测试和调试
目录: 07-Testing
测试源生成器,确保代码质量。
学习内容:
- 编写生成器测试
- 验证生成的代码
- 测试诊断信息
- 调试技巧
7. .NET 10 [Embedded] 特性
目录: 08-DotNet10-Embedded
使用 .NET 10 的 [Embedded] 特性解决 CS0436 警告。
学习内容:
- AddEmbeddedAttributeDefinition() API
- [Embedded] 特性的作用
- 解决 InternalsVisibleTo 冲突
- .NET 10 新特性
运行示例
每个示例都是独立的项目,可以单独运行:
cd 01-HelloWorld
dotnet build
dotnet run --project HelloWorld.Consumer学习路径
建议按照以下顺序学习:
- 基础 → Hello World
- 性能 → 增量生成器
- 实用 → ToString 生成器、Builder 生成器
- 质量 → 诊断报告、单元测试
- 高级 → .NET 10 嵌入式资源
相关资源
示例分类
按难度分类
按主题分类
| 主题 | 示例 | 说明 |
|---|---|---|
| 基础入门 | Hello World | 最简单的源生成器 |
| 性能优化 | 增量生成器 | 提高生成器性能 |
| 代码生成 | ToString、Builder | 实用的代码生成模式 |
| 错误处理 | 诊断报告 | 报告编译错误和警告 |
| 质量保证 | 测试调试 | 测试和调试技术 |
| 新特性 | .NET 10 嵌入式 | 最新的 .NET 特性 |
学习路径图
学习路径说明
第一步:Hello World (必修)
- 时间:30 分钟
- 难度:⭐
- 目标:理解源生成器的基本概念
第二步:选择方向 (二选一)
路径 A:性能优化 → 增量生成器
- 适合:关注性能的开发者
- 时间:1-2 小时
- 难度:⭐⭐⭐
路径 B:实用功能 → ToString 生成器
- 适合:想快速上手的开发者
- 时间:1 小时
- 难度:⭐⭐
第三步:Builder 生成器 (必修)
- 时间:2-3 小时
- 难度:⭐⭐⭐⭐
- 目标:掌握复杂代码生成
第四步:诊断报告 (必修)
- 时间:1-2 小时
- 难度:⭐⭐⭐
- 目标:学会错误处理
第五步:测试调试 (必修)
- 时间:2-3 小时
- 难度:⭐⭐⭐⭐
- 目标:保证代码质量
第六步:.NET 10 嵌入式 (选修)
- 时间:1 小时
- 难度:⭐⭐⭐
- 目标:了解最新特性
难度分布
示例对比表
| 示例 | 难度 | 时间 | 关键技术 | 适用场景 |
|---|---|---|---|---|
| Hello World | ⭐ | 30min | ISourceGenerator | 学习基础 |
| 增量生成器 | ⭐⭐⭐ | 1-2h | IIncrementalGenerator, 管道 | 性能优化 |
| ToString 生成器 | ⭐⭐ | 1h | 特性、属性分析 | 自动生成方法 |
| Builder 生成器 | ⭐⭐⭐⭐ | 2-3h | 复杂代码生成、流畅接口 | 设计模式 |
| 诊断报告 | ⭐⭐⭐ | 1-2h | DiagnosticDescriptor | 错误处理 |
| 测试调试 | ⭐⭐⭐⭐ | 2-3h | 单元测试、快照测试 | 质量保证 |
| .NET 10 嵌入式 | ⭐⭐⭐ | 1h | [Embedded] 特性 | 解决冲突 |
技术栈对比
| 示例 | 语法树 | 语义模型 | 符号 | 特性 | 诊断 | 测试 |
|---|---|---|---|---|---|---|
| Hello World | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| 增量生成器 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| ToString 生成器 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| Builder 生成器 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| 诊断报告 | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| 测试调试 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| .NET 10 嵌入式 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
推荐学习顺序
快速入门路径(3-4 小时)
适合想快速了解源生成器的开发者:
- Hello World (30min) - 理解基本概念
- ToString 生成器 (1h) - 学习实用技术
- 诊断报告 (1-2h) - 掌握错误处理
完整学习路径(10-15 小时)
适合想深入掌握源生成器的开发者:
- Hello World (30min)
- ToString 生成器 (1h)
- 增量生成器 (1-2h)
- Builder 生成器 (2-3h)
- 诊断报告 (1-2h)
- 测试调试 (2-3h)
- . NET 10 嵌入式 (1h)
性能优化路径(4-6 小时)
适合关注性能的开发者:
- Hello World (30min)
- 增量生成器 (1-2h) - 重点学习
- Builder 生成器 (2-3h)
- 测试调试 (2-3h) - 性能测试
实战应用路径(6-8 小时)
适合想快速应用到项目的开发者:
- Hello World (30min)
- ToString 生成器 (1h)
- Builder 生成器 (2-3h)
- 诊断报告 (1-2h)
- 测试调试 (2-3h)
运行示例
前置要求
- .NET SDK 6.0 或更高版本
- Visual Studio 2022 或 VS Code
- C# 扩展(VS Code)
运行步骤
# 1. 克隆仓库
git clone https://github.com/your-repo/roslyn-source-generators.git
cd roslyn-source-generators
# 2. 进入示例目录
cd 01-HelloWorld
# 3. 构建项目
dotnet build
# 4. 运行消费者项目
dotnet run --project HelloWorld.Consumer
# 5. 查看生成的代码
# 生成的代码位于: obj/Debug/net6.0/generated/调试生成器
# 方法 1: 使用 Debugger.Launch()
# 在生成器代码中添加:
System.Diagnostics.Debugger.Launch();
# 方法 2: 附加到进程
# 1. 启动构建
dotnet build
# 2. 在 Visual Studio 中附加到 dotnet.exe 进程查看生成的代码
生成的代码位于:
obj/Debug/net6.0/generated/[GeneratorName]/[GeneratorName]/[FileName].g.cs或者在 Visual Studio 中:
- 展开项目节点
- 展开 "Dependencies" → "Analyzers" → "[GeneratorName]"
- 查看生成的文件
常见问题
Q1: 为什么我的生成器没有运行?
A: 检查以下几点:
- 生成器项目是否正确引用到消费者项目
- 生成器项目的
OutputItemType是否设置为Analyzer - 是否清理并重新构建了项目
<ItemGroup>
<ProjectReference Include="..\YourGenerator\YourGenerator.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>Q2: 如何查看生成的代码?
A: 有三种方法:
- 在
obj/Debug/net6.0/generated/目录中查看 - 在 Visual Studio 的解决方案资源管理器中展开 "Analyzers"
- 使用
EmitCompilerGeneratedFiles属性:
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>Q3: 生成器报错怎么办?
A: 调试步骤:
- 在生成器中添加
Debugger.Launch() - 使用
context.ReportDiagnostic()输出调试信息 - 检查生成器的异常日志
- 使用单元测试验证生成器逻辑
Q4: 增量生成器和传统生成器有什么区别?
A: 主要区别:
- 性能:增量生成器只在输入改变时重新运行
- API:增量生成器使用管道 API
- 复杂度:增量生成器需要更多的设置代码
- 推荐:新项目应该使用增量生成器
Q5: 如何测试源生成器?
A: 三种测试方法:
- 单元测试:使用
CSharpGeneratorDriver测试生成逻辑 - 快照测试:比较生成的代码和预期的代码
- 集成测试:在实际项目中测试生成器
参考 测试调试示例 了解详情。
Q6: 生成的代码有 CS0436 警告怎么办?
A: 使用 .NET 10 的 [Embedded] 特性:
context.AddEmbeddedAttributeDefinition();参考 .NET 10 嵌入式示例 了解详情。
Q7: 如何在生成器中使用第三方库?
A: 注意事项:
- 生成器在编译时运行,不能依赖运行时库
- 只能使用 .NET Standard 2.0 兼容的库
- 避免使用大型依赖,影响编译性能
- 考虑将库代码内联到生成器中
Q8: 生成器性能很慢怎么办?
A: 优化建议:
- 使用增量生成器 API
- 缓存计算结果
- 避免重复遍历语法树
- 使用
CreateSyntaxProvider进行两阶段过滤 - 减少生成的代码量
参考 增量生成器示例 了解详情。
相关资源
官方文档
学习指南
API 参考
社区资源
最后更新: 2025-01-21
示例代码结构
标准项目结构
每个示例都遵循相同的项目结构,便于理解和学习:
示例目录/
├── README.md # 示例说明文档
├── 示例名称.slnx # 解决方案文件
├── 示例名称.Generator/ # 生成器项目
│ ├── 示例名称Generator.cs # 主生成器类
│ ├── 示例名称.csproj # 项目文件
│ └── ... # 其他辅助类
└── 示例名称.Consumer/ # 消费者项目
├── Program.cs # 主程序
├── 示例类.cs # 使用生成器的类
└── 示例名称.Consumer.csproj # 项目文件生成器项目配置
所有生成器项目都包含以下关键配置:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
</ItemGroup>
</Project>消费者项目配置
消费者项目引用生成器的标准方式:
<ItemGroup>
<ProjectReference Include="..\示例名称.Generator\示例名称.Generator.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
<!-- 可选:输出生成的文件 -->
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>示例特色功能
Hello World 示例特色
- 最简实现:仅 30 行代码实现完整生成器
- 清晰注释:每行代码都有详细的中文注释
- 即时反馈:修改代码后立即看到生成结果
- 零配置:无需任何特性或标记
适合人群:
- 完全没有源生成器经验的开发者
- 想快速了解源生成器工作原理的开发者
- 需要一个最小化示例作为起点的开发者
增量生成器示例特色
- 性能对比:包含传统生成器和增量生成器的性能对比
- 管道可视化:详细的管道操作流程图
- 缓存策略:展示如何有效利用缓存
- 性能测试:包含性能测试代码和结果
适合人群:
- 关注编译性能的开发者
- 需要处理大型项目的开发者
- 想了解增量生成器原理的开发者
ToString 生成器示例特色
- 实用性强:可以直接用于生产环境
- 可配置:支持多种格式化选项
- 智能分析:自动识别属性类型并格式化
- 错误处理:完善的错误提示和诊断
适合人群:
- 需要自动生成 ToString 方法的开发者
- 想学习特性驱动代码生成的开发者
- 需要一个实用示例的开发者
Builder 生成器示例特色
- 设计模式:完整实现 Builder 模式
- 流畅接口:生成易用的流畅 API
- 类型安全:编译时类型检查
- 复杂生成:展示如何生成复杂的嵌套类
适合人群:
- 需要实现 Builder 模式的开发者
- 想学习复杂代码生成的开发者
- 关注 API 设计的开发者
诊断报告示例特色
- 完整诊断:涵盖错误、警告、信息三个级别
- 精确定位:准确指出错误位置
- 友好提示:清晰的错误消息和修复建议
- 本地化支持:支持多语言错误消息
适合人群:
- 需要提供友好错误提示的开发者
- 想学习诊断 API 的开发者
- 关注用户体验的开发者
测试调试示例特色
- 完整测试套件:单元测试、快照测试、集成测试
- 调试技巧:多种调试方法和工具
- CI/CD 集成:包含 GitHub Actions 配置
- 测试辅助类:可复用的测试工具类
适合人群:
- 需要测试源生成器的开发者
- 想学习调试技巧的开发者
- 关注代码质量的开发者
.NET 10 嵌入式示例特色
- 最新特性:展示 .NET 10 的新 API
- 问题解决:解决 CS0436 警告
- 向后兼容:支持旧版本 .NET 的方案
- 最佳实践:推荐的特性使用方式
适合人群:
- 使用 .NET 10 的开发者
- 遇到 CS0436 警告的开发者
- 想了解最新特性的开发者
学习建议
初学者建议
不要跳过 Hello World
- 即使你有编程经验,也要从 Hello World 开始
- 理解基本概念比快速完成更重要
- 花时间理解每一行代码的作用
动手实践
- 不要只是阅读代码,要亲自运行和修改
- 尝试修改生成的代码,观察结果
- 实验不同的输入,看看生成器如何响应
循序渐进
- 按照推荐的学习路径学习
- 不要急于学习高级示例
- 确保理解当前示例再继续下一个
记录笔记
- 记录遇到的问题和解决方案
- 总结每个示例的关键点
- 建立自己的知识库
进阶开发者建议
深入理解原理
- 不要满足于"能用就行"
- 理解增量生成器的缓存机制
- 学习 Roslyn API 的设计思想
性能优化
- 使用性能分析工具
- 对比不同实现的性能
- 学习缓存和批处理技巧
代码质量
- 编写完整的单元测试
- 使用代码分析工具
- 遵循最佳实践和编码规范
实际应用
- 将学到的知识应用到实际项目
- 解决实际问题,而不是只做练习
- 分享经验,帮助其他开发者
团队学习建议
结对学习
- 两人一组,一起学习示例
- 互相讨论和解答问题
- 分享不同的理解和见解
代码审查
- 审查彼此编写的生成器代码
- 提供建设性的反馈
- 学习他人的优秀实践
知识分享
- 定期举办技术分享会
- 分享学习心得和实践经验
- 建立团队知识库
项目实践
- 在团队项目中应用源生成器
- 解决实际的业务问题
- 总结最佳实践和反模式
扩展练习
Hello World 扩展
- 添加参数:修改生成器,接受参数并生成不同的问候语
- 多个类:生成多个类而不是一个
- 命名空间:支持自定义命名空间
ToString 生成器扩展
- 格式化选项:添加更多格式化选项(JSON、XML 等)
- 继承支持:支持包含基类属性
- 集合处理:特殊处理集合类型的属性
Builder 生成器扩展
- 验证逻辑:在 Build 方法中添加验证
- 默认值:支持属性默认值
- 不可变对象:生成不可变的 Builder
诊断报告扩展
- 代码修复:添加自动修复建议
- 配置文件:支持通过配置文件自定义诊断规则
- 严重级别:根据上下文动态调整严重级别
测试调试扩展
- 属性测试:添加基于属性的测试
- 性能基准:添加性能基准测试
- 覆盖率报告:生成测试覆盖率报告
故障排除
常见错误
错误 1: 生成器未运行
症状:构建成功,但没有生成代码
可能原因:
- 项目引用配置错误
- 生成器类没有正确实现接口
- 生成器抛出了异常
解决方案:
- 检查项目引用的
OutputItemType和ReferenceOutputAssembly - 确保生成器类有
[Generator]特性 - 添加 try-catch 捕获异常并报告诊断
错误 2: CS0436 警告
症状:编译时出现 CS0436 警告
原因:多个程序集定义了相同的类型
解决方案:
- 使用 .NET 10 的
[Embedded]特性 - 或者使用
#pragma warning disable CS0436
错误 3: 生成的代码有编译错误
症状:生成的代码无法编译
可能原因:
- 生成的代码语法错误
- 缺少必要的 using 语句
- 命名空间冲突
解决方案:
- 查看生成的代码文件
- 使用 Roslyn API 验证生成的代码
- 添加单元测试验证生成逻辑
错误 4: 性能问题
症状:编译时间显著增加
可能原因:
- 使用了传统生成器而不是增量生成器
- 重复遍历语法树
- 生成了大量代码
解决方案:
- 迁移到增量生成器 API
- 使用缓存避免重复计算
- 优化生成的代码量
下一步
完成示例学习后,你可以:
深入学习 Roslyn API
探索高级主题
实际应用
- 在你的项目中应用源生成器
- 解决实际的业务问题
- 分享你的经验和成果
贡献社区
- 提交 Issue 和 Pull Request
- 分享你的示例和经验
- 帮助其他开发者
文档版本: 2.0
最后更新: 2025-01-21
贡献者: Roslyn 源生成器学习项目团队