Skip to content

示例项目

本项目包含 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 新特性

查看详情

运行示例

每个示例都是独立的项目,可以单独运行:

bash
cd 01-HelloWorld
dotnet build
dotnet run --project HelloWorld.Consumer

学习路径

建议按照以下顺序学习:

  1. 基础 → Hello World
  2. 性能 → 增量生成器
  3. 实用 → ToString 生成器、Builder 生成器
  4. 质量 → 诊断报告、单元测试
  5. 高级 → .NET 10 嵌入式资源

相关资源

示例分类

按难度分类

按主题分类

主题示例说明
基础入门Hello World最简单的源生成器
性能优化增量生成器提高生成器性能
代码生成ToString、Builder实用的代码生成模式
错误处理诊断报告报告编译错误和警告
质量保证测试调试测试和调试技术
新特性.NET 10 嵌入式最新的 .NET 特性

学习路径图

学习路径说明

  1. 第一步:Hello World (必修)

    • 时间:30 分钟
    • 难度:⭐
    • 目标:理解源生成器的基本概念
  2. 第二步:选择方向 (二选一)

    • 路径 A:性能优化 → 增量生成器

      • 适合:关注性能的开发者
      • 时间:1-2 小时
      • 难度:⭐⭐⭐
    • 路径 B:实用功能 → ToString 生成器

      • 适合:想快速上手的开发者
      • 时间:1 小时
      • 难度:⭐⭐
  3. 第三步:Builder 生成器 (必修)

    • 时间:2-3 小时
    • 难度:⭐⭐⭐⭐
    • 目标:掌握复杂代码生成
  4. 第四步:诊断报告 (必修)

    • 时间:1-2 小时
    • 难度:⭐⭐⭐
    • 目标:学会错误处理
  5. 第五步:测试调试 (必修)

    • 时间:2-3 小时
    • 难度:⭐⭐⭐⭐
    • 目标:保证代码质量
  6. 第六步:.NET 10 嵌入式 (选修)

    • 时间:1 小时
    • 难度:⭐⭐⭐
    • 目标:了解最新特性

难度分布


示例对比表

示例难度时间关键技术适用场景
Hello World30minISourceGenerator学习基础
增量生成器⭐⭐⭐1-2hIIncrementalGenerator, 管道性能优化
ToString 生成器⭐⭐1h特性、属性分析自动生成方法
Builder 生成器⭐⭐⭐⭐2-3h复杂代码生成、流畅接口设计模式
诊断报告⭐⭐⭐1-2hDiagnosticDescriptor错误处理
测试调试⭐⭐⭐⭐2-3h单元测试、快照测试质量保证
.NET 10 嵌入式⭐⭐⭐1h[Embedded] 特性解决冲突

技术栈对比

示例语法树语义模型符号特性诊断测试
Hello World
增量生成器
ToString 生成器
Builder 生成器
诊断报告
测试调试
.NET 10 嵌入式

推荐学习顺序

快速入门路径(3-4 小时)

适合想快速了解源生成器的开发者:

  1. Hello World (30min) - 理解基本概念
  2. ToString 生成器 (1h) - 学习实用技术
  3. 诊断报告 (1-2h) - 掌握错误处理

完整学习路径(10-15 小时)

适合想深入掌握源生成器的开发者:

  1. Hello World (30min)
  2. ToString 生成器 (1h)
  3. 增量生成器 (1-2h)
  4. Builder 生成器 (2-3h)
  5. 诊断报告 (1-2h)
  6. 测试调试 (2-3h)
  7. . NET 10 嵌入式 (1h)

性能优化路径(4-6 小时)

适合关注性能的开发者:

  1. Hello World (30min)
  2. 增量生成器 (1-2h) - 重点学习
  3. Builder 生成器 (2-3h)
  4. 测试调试 (2-3h) - 性能测试

实战应用路径(6-8 小时)

适合想快速应用到项目的开发者:

  1. Hello World (30min)
  2. ToString 生成器 (1h)
  3. Builder 生成器 (2-3h)
  4. 诊断报告 (1-2h)
  5. 测试调试 (2-3h)

运行示例

前置要求

  • .NET SDK 6.0 或更高版本
  • Visual Studio 2022 或 VS Code
  • C# 扩展(VS Code)

运行步骤

bash
# 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/

调试生成器

bash
# 方法 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 中:

  1. 展开项目节点
  2. 展开 "Dependencies" → "Analyzers" → "[GeneratorName]"
  3. 查看生成的文件

常见问题

Q1: 为什么我的生成器没有运行?

A: 检查以下几点:

  1. 生成器项目是否正确引用到消费者项目
  2. 生成器项目的 OutputItemType 是否设置为 Analyzer
  3. 是否清理并重新构建了项目
xml
<ItemGroup>
  <ProjectReference Include="..\YourGenerator\YourGenerator.csproj"
                    OutputItemType="Analyzer"
                    ReferenceOutputAssembly="false" />
</ItemGroup>

Q2: 如何查看生成的代码?

A: 有三种方法:

  1. obj/Debug/net6.0/generated/ 目录中查看
  2. 在 Visual Studio 的解决方案资源管理器中展开 "Analyzers"
  3. 使用 EmitCompilerGeneratedFiles 属性:
xml
<PropertyGroup>
  <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
  <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

Q3: 生成器报错怎么办?

A: 调试步骤:

  1. 在生成器中添加 Debugger.Launch()
  2. 使用 context.ReportDiagnostic() 输出调试信息
  3. 检查生成器的异常日志
  4. 使用单元测试验证生成器逻辑

Q4: 增量生成器和传统生成器有什么区别?

A: 主要区别:

  • 性能:增量生成器只在输入改变时重新运行
  • API:增量生成器使用管道 API
  • 复杂度:增量生成器需要更多的设置代码
  • 推荐:新项目应该使用增量生成器

Q5: 如何测试源生成器?

A: 三种测试方法:

  1. 单元测试:使用 CSharpGeneratorDriver 测试生成逻辑
  2. 快照测试:比较生成的代码和预期的代码
  3. 集成测试:在实际项目中测试生成器

参考 测试调试示例 了解详情。

Q6: 生成的代码有 CS0436 警告怎么办?

A: 使用 .NET 10 的 [Embedded] 特性:

csharp
context.AddEmbeddedAttributeDefinition();

参考 .NET 10 嵌入式示例 了解详情。

Q7: 如何在生成器中使用第三方库?

A: 注意事项:

  1. 生成器在编译时运行,不能依赖运行时库
  2. 只能使用 .NET Standard 2.0 兼容的库
  3. 避免使用大型依赖,影响编译性能
  4. 考虑将库代码内联到生成器中

Q8: 生成器性能很慢怎么办?

A: 优化建议:

  1. 使用增量生成器 API
  2. 缓存计算结果
  3. 避免重复遍历语法树
  4. 使用 CreateSyntaxProvider 进行两阶段过滤
  5. 减少生成的代码量

参考 增量生成器示例 了解详情。


相关资源

官方文档

学习指南

API 参考

社区资源


最后更新: 2025-01-21

示例代码结构

标准项目结构

每个示例都遵循相同的项目结构,便于理解和学习:

示例目录/
├── README.md                    # 示例说明文档
├── 示例名称.slnx                # 解决方案文件
├── 示例名称.Generator/          # 生成器项目
│   ├── 示例名称Generator.cs     # 主生成器类
│   ├── 示例名称.csproj          # 项目文件
│   └── ...                      # 其他辅助类
└── 示例名称.Consumer/           # 消费者项目
    ├── Program.cs               # 主程序
    ├── 示例类.cs                # 使用生成器的类
    └── 示例名称.Consumer.csproj # 项目文件

生成器项目配置

所有生成器项目都包含以下关键配置:

xml
<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>

消费者项目配置

消费者项目引用生成器的标准方式:

xml
<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 警告的开发者
  • 想了解最新特性的开发者

学习建议

初学者建议

  1. 不要跳过 Hello World

    • 即使你有编程经验,也要从 Hello World 开始
    • 理解基本概念比快速完成更重要
    • 花时间理解每一行代码的作用
  2. 动手实践

    • 不要只是阅读代码,要亲自运行和修改
    • 尝试修改生成的代码,观察结果
    • 实验不同的输入,看看生成器如何响应
  3. 循序渐进

    • 按照推荐的学习路径学习
    • 不要急于学习高级示例
    • 确保理解当前示例再继续下一个
  4. 记录笔记

    • 记录遇到的问题和解决方案
    • 总结每个示例的关键点
    • 建立自己的知识库

进阶开发者建议

  1. 深入理解原理

    • 不要满足于"能用就行"
    • 理解增量生成器的缓存机制
    • 学习 Roslyn API 的设计思想
  2. 性能优化

    • 使用性能分析工具
    • 对比不同实现的性能
    • 学习缓存和批处理技巧
  3. 代码质量

    • 编写完整的单元测试
    • 使用代码分析工具
    • 遵循最佳实践和编码规范
  4. 实际应用

    • 将学到的知识应用到实际项目
    • 解决实际问题,而不是只做练习
    • 分享经验,帮助其他开发者

团队学习建议

  1. 结对学习

    • 两人一组,一起学习示例
    • 互相讨论和解答问题
    • 分享不同的理解和见解
  2. 代码审查

    • 审查彼此编写的生成器代码
    • 提供建设性的反馈
    • 学习他人的优秀实践
  3. 知识分享

    • 定期举办技术分享会
    • 分享学习心得和实践经验
    • 建立团队知识库
  4. 项目实践

    • 在团队项目中应用源生成器
    • 解决实际的业务问题
    • 总结最佳实践和反模式

扩展练习

Hello World 扩展

  1. 添加参数:修改生成器,接受参数并生成不同的问候语
  2. 多个类:生成多个类而不是一个
  3. 命名空间:支持自定义命名空间

ToString 生成器扩展

  1. 格式化选项:添加更多格式化选项(JSON、XML 等)
  2. 继承支持:支持包含基类属性
  3. 集合处理:特殊处理集合类型的属性

Builder 生成器扩展

  1. 验证逻辑:在 Build 方法中添加验证
  2. 默认值:支持属性默认值
  3. 不可变对象:生成不可变的 Builder

诊断报告扩展

  1. 代码修复:添加自动修复建议
  2. 配置文件:支持通过配置文件自定义诊断规则
  3. 严重级别:根据上下文动态调整严重级别

测试调试扩展

  1. 属性测试:添加基于属性的测试
  2. 性能基准:添加性能基准测试
  3. 覆盖率报告:生成测试覆盖率报告

故障排除

常见错误

错误 1: 生成器未运行

症状:构建成功,但没有生成代码

可能原因

  • 项目引用配置错误
  • 生成器类没有正确实现接口
  • 生成器抛出了异常

解决方案

  1. 检查项目引用的 OutputItemTypeReferenceOutputAssembly
  2. 确保生成器类有 [Generator] 特性
  3. 添加 try-catch 捕获异常并报告诊断

错误 2: CS0436 警告

症状:编译时出现 CS0436 警告

原因:多个程序集定义了相同的类型

解决方案

  • 使用 .NET 10 的 [Embedded] 特性
  • 或者使用 #pragma warning disable CS0436

错误 3: 生成的代码有编译错误

症状:生成的代码无法编译

可能原因

  • 生成的代码语法错误
  • 缺少必要的 using 语句
  • 命名空间冲突

解决方案

  1. 查看生成的代码文件
  2. 使用 Roslyn API 验证生成的代码
  3. 添加单元测试验证生成逻辑

错误 4: 性能问题

症状:编译时间显著增加

可能原因

  • 使用了传统生成器而不是增量生成器
  • 重复遍历语法树
  • 生成了大量代码

解决方案

  1. 迁移到增量生成器 API
  2. 使用缓存避免重复计算
  3. 优化生成的代码量

下一步

完成示例学习后,你可以:

  1. 深入学习 Roslyn API

  2. 探索高级主题

  3. 实际应用

    • 在你的项目中应用源生成器
    • 解决实际的业务问题
    • 分享你的经验和成果
  4. 贡献社区

    • 提交 Issue 和 Pull Request
    • 分享你的示例和经验
    • 帮助其他开发者

文档版本: 2.0
最后更新: 2025-01-21
贡献者: Roslyn 源生成器学习项目团队

基于 MIT 许可发布