Roslyn API 完整参考文档
深入、全面的 Roslyn 源生成器 API 参考指南
📚 文档结构
本 API 参考文档分为多个独立的章节,每个章节深入讲解 Roslyn API 的特定领域。
核心文档
- 符号系统详解
- 类型系统深入
- 特性处理
- 符号比较和等价性
- 类型转换和兼容性
- 编译创建和配置
- 元数据引用管理
- 程序集加载和解析
- 跨程序集符号查找
- 编译选项和优化
- SyntaxFactory 完整指南
- 代码构建模式
- 格式化和美化
- 复杂结构生成
- 字符串插值 vs SyntaxFactory
- 诊断描述符设计
- 诊断报告策略
- 严重级别选择
- 位置和范围
- 诊断抑制
- 管道操作详解
- 数据流转换
- 缓存机制
- 性能优化
- 调试管道
- 类型层次结构
- 泛型类型处理
- 可空类型
- 数组和集合类型
- 特殊类型
- 表达式语法节点
- 语句语法节点
- 控制流分析
- 数据流分析
- 性能优化技巧
- 内存管理
- 并发处理
- 错误处理模式
- 测试策略
实用指南
- 序列化生成器
- ORM 映射生成器
- 依赖注入生成器
- 日志生成器
- API 客户端生成器
- 调试生成器
- 性能分析
- 常见错误
- 故障排除
- 代码组织
- 命名约定
- 错误处理
- 性能考虑
- 可维护性
- 常见错误
- 性能陷阱
- 内存泄漏
- 线程安全问题
🎯 快速导航
按任务查找
按 API 类型查找
- ISymbol 相关 → 语义模型 API
- SyntaxNode 相关 → LEARNING_GUIDE.md
- Compilation 相关 → 编译 API
- SyntaxFactory 相关 → 代码生成 API
- Diagnostic 相关 → 诊断 API
📖 阅读建议
初学者路径
- 先阅读 LEARNING_GUIDE.md 了解基础
- 阅读 语义模型 API 理解符号系统
- 阅读 代码生成 API 学习如何生成代码
- 阅读 常见场景实现 看实际例子
进阶路径
问题解决路径
遇到问题时:
🔗 相关资源
- 主 README - 项目介绍和快速开始
- LEARNING_GUIDE.md - 学习指南和基础 API
- 示例项目 - 7 个渐进式示例
- 概念文档 - 核心概念详解
📝 文档约定
代码示例
所有代码示例都包含:
- ✅ 完整的代码(可以直接运行)
- ✅ 详细的中文注释
- ✅ 输入和输出示例
- ✅ 常见错误和解决方案
图表
使用 Mermaid 图表展示:
- 🔷 架构图 - 展示组件关系
- 🔄 流程图 - 展示处理流程
- ⏱️ 时序图 - 展示调用顺序
- 📊 状态图 - 展示状态转换
最佳实践标记
- ✅ 推荐做法 - 应该这样做
- ❌ 反模式 - 不应该这样做
- ⚠️ 注意事项 - 需要特别注意
- 💡 技巧 - 实用技巧
- 🚀 性能 - 性能相关
- 🐛 常见错误 - 容易犯的错误
🤝 贡献
发现错误或有改进建议?欢迎提交 Issue 或 Pull Request!
最后更新: 2025-01-21
API 分类详解
核心 API 层次结构
API 分类说明
1. 编译和元数据 API
用途: 创建和管理编译单元,处理程序集引用
核心类型:
Compilation- 编译单元MetadataReference- 元数据引用SyntaxTree- 语法树CompilationOptions- 编译选项
适用场景:
- 创建编译上下文
- 加载外部程序集
- 配置编译选项
- 跨程序集符号查找
文档: 编译 API
2. 语法分析 API
用途: 解析和操作 C# 代码的语法结构
核心类型:
SyntaxNode- 语法节点基类SyntaxToken- 语法标记SyntaxTrivia- 语法琐碎内容(注释、空白)SyntaxFactory- 语法节点工厂
适用场景:
- 解析源代码
- 遍历语法树
- 查找特定语法结构
- 生成新的语法节点
文档: 语法树指南
3. 语义分析 API
用途: 获取代码的语义信息和类型信息
核心类型:
SemanticModel- 语义模型ISymbol- 符号基接口ITypeSymbol- 类型符号SymbolInfo- 符号信息
适用场景:
- 获取类型信息
- 解析符号引用
- 类型检查和转换
- 特性处理
文档: 语义模型 API
4. 符号系统 API
用途: 表示和操作代码中的各种符号
核心类型:
INamedTypeSymbol- 命名类型符号IMethodSymbol- 方法符号IPropertySymbol- 属性符号IFieldSymbol- 字段符号
适用场景:
- 分析类型成员
- 检查继承关系
- 处理泛型类型
- 符号比较
文档: 符号指南
5. 代码生成 API
用途: 生成新的 C# 代码
核心类型:
SyntaxFactory- 语法工厂SyntaxGenerator- 语法生成器SourceText- 源文本StringBuilder- 字符串构建器
适用场景:
- 生成类和方法
- 构建复杂表达式
- 格式化代码
- 添加注释和文档
文档: 代码生成 API
6. 诊断 API
用途: 报告编译错误、警告和信息
核心类型:
Diagnostic- 诊断信息DiagnosticDescriptor- 诊断描述符DiagnosticSeverity- 严重级别Location- 位置信息
适用场景:
- 报告错误
- 发出警告
- 提供信息提示
- 代码分析
文档: 诊断 API
7. 增量生成器 API
用途: 构建高性能的增量源生成器
核心类型:
IIncrementalGenerator- 增量生成器接口IncrementalValueProvider<T>- 增量值提供器IncrementalValuesProvider<T>- 增量值集合提供器IncrementalGeneratorInitializationContext- 初始化上下文
适用场景:
- 性能优化
- 缓存中间结果
- 增量更新
- 大型项目
文档: 增量生成器管道
学习路径图
初学者学习路径
进阶学习路径
专家学习路径
API 使用指南
基本使用模式
模式 1: 查找并处理类
csharp
// 1. 获取语义模型
var semanticModel = compilation.GetSemanticModel(syntaxTree);
// 2. 查找类声明
var classDeclarations = syntaxTree.GetRoot()
.DescendantNodes()
.OfType<ClassDeclarationSyntax>();
// 3. 获取符号信息
foreach (var classDecl in classDeclarations)
{
var classSymbol = semanticModel.GetDeclaredSymbol(classDecl) as INamedTypeSymbol;
// 4. 处理类成员
foreach (var member in classSymbol.GetMembers())
{
// 处理成员...
}
}模式 2: 生成代码
csharp
// 1. 使用 SyntaxFactory 生成语法节点
var classDeclaration = SyntaxFactory.ClassDeclaration("MyClass")
.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
.AddMembers(
SyntaxFactory.MethodDeclaration(
SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)),
"MyMethod")
.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
.WithBody(SyntaxFactory.Block())
);
// 2. 格式化代码
var formattedCode = classDeclaration.NormalizeWhitespace().ToFullString();
// 3. 添加到编译
context.AddSource("MyClass.g.cs", SourceText.From(formattedCode, Encoding.UTF8));模式 3: 报告诊断
csharp
// 1. 定义诊断描述符
private static readonly DiagnosticDescriptor Rule = new(
id: "GEN001",
title: "类必须是 partial",
messageFormat: "类 '{0}' 必须声明为 partial",
category: "Generator",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);
// 2. 创建诊断
var diagnostic = Diagnostic.Create(
Rule,
classDeclaration.Identifier.GetLocation(),
classSymbol.Name);
// 3. 报告诊断
context.ReportDiagnostic(diagnostic);增量生成器模式
csharp
public void Initialize(IncrementalGeneratorInitializationContext context)
{
// 1. 创建管道
var classDeclarations = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (node, _) => node is ClassDeclarationSyntax,
transform: static (ctx, _) => GetClassInfo(ctx))
.Where(static m => m is not null);
// 2. 组合数据
var compilationAndClasses = context.CompilationProvider
.Combine(classDeclarations.Collect());
// 3. 注册输出
context.RegisterSourceOutput(compilationAndClasses,
static (spc, source) => Execute(source.Left, source.Right, spc));
}常见使用模式
模式 1: 特性驱动生成
csharp
// 查找带有特定特性的类
var markedClasses = context.SyntaxProvider
.ForAttributeWithMetadataName(
"MyNamespace.MyAttribute",
predicate: static (node, _) => node is ClassDeclarationSyntax,
transform: static (ctx, _) => GetClassInfo(ctx));
// 为每个标记的类生成代码
context.RegisterSourceOutput(markedClasses,
static (spc, classInfo) => GenerateCode(classInfo, spc));模式 2: 接口实现生成
csharp
// 查找实现特定接口的类
var implementingClasses = compilation.GetSymbolsWithName(
name => true,
SymbolFilter.Type)
.OfType<INamedTypeSymbol>()
.Where(type => type.AllInterfaces.Any(i =>
i.Name == "IMyInterface"));
// 为每个类生成实现代码
foreach (var classSymbol in implementingClasses)
{
var code = GenerateImplementation(classSymbol);
context.AddSource($"{classSymbol.Name}.g.cs", code);
}模式 3: 部分类扩展
csharp
// 查找 partial 类
var partialClasses = syntaxTree.GetRoot()
.DescendantNodes()
.OfType<ClassDeclarationSyntax>()
.Where(c => c.Modifiers.Any(SyntaxKind.PartialKeyword));
// 为每个 partial 类生成扩展
foreach (var classDecl in partialClasses)
{
var classSymbol = semanticModel.GetDeclaredSymbol(classDecl);
var extension = GenerateExtension(classSymbol);
context.AddSource($"{classSymbol.Name}.Extension.g.cs", extension);
}模式 4: 配置驱动生成
csharp
// 读取配置文件
var configFiles = context.AdditionalTextsProvider
.Where(static file => file.Path.EndsWith(".generator.json"));
// 解析配置并生成代码
context.RegisterSourceOutput(configFiles,
static (spc, configFile) =>
{
var config = ParseConfig(configFile.GetText()?.ToString());
var code = GenerateFromConfig(config);
spc.AddSource("Generated.g.cs", code);
});性能考虑
性能优化原则
性能最佳实践
1. 使用增量生成器
csharp
// ✅ 推荐:增量生成器
[Generator]
public class MyGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
// 增量管道会自动缓存结果
var provider = context.SyntaxProvider.CreateSyntaxProvider(...);
}
}
// ❌ 避免:传统生成器
[Generator]
public class OldGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
// 每次都重新计算
}
}2. 最小化内存分配
csharp
// ✅ 推荐:使用 StringBuilder
var sb = new StringBuilder();
sb.AppendLine("public class MyClass");
sb.AppendLine("{");
sb.AppendLine("}");
var code = sb.ToString();
// ❌ 避免:字符串拼接
var code = "";
code += "public class MyClass\n";
code += "{\n";
code += "}\n";3. 使用 Span<T> 和 Memory<T>
csharp
// ✅ 推荐:使用 Span
ReadOnlySpan<char> span = text.AsSpan();
var substring = span.Slice(start, length);
// ❌ 避免:创建子字符串
var substring = text.Substring(start, length);4. 缓存常用符号
csharp
// ✅ 推荐:缓存符号
private static INamedTypeSymbol? _stringSymbol;
private static INamedTypeSymbol GetStringSymbol(Compilation compilation)
{
return _stringSymbol ??= compilation.GetSpecialType(SpecialType.System_String);
}
// ❌ 避免:重复查找
var stringSymbol = compilation.GetSpecialType(SpecialType.System_String);版本兼容性
Roslyn 版本对应关系
| .NET 版本 | Roslyn 版本 | 主要特性 |
|---|---|---|
| .NET 5.0 | 3.8+ | 源生成器 v1 |
| .NET 6.0 | 4.0+ | 增量生成器 |
| .NET 7.0 | 4.3+ | 性能改进 |
| .NET 8.0 | 4.8+ | 新的 API |
| .NET 9.0 | 4.11+ | 更多优化 |
| .NET 10.0 | 4.14+ | [Embedded] 特性 |
API 可用性
csharp
// 检查 API 可用性
#if ROSLYN4_0_OR_GREATER
// 使用增量生成器
public class MyGenerator : IIncrementalGenerator { }
#else
// 使用传统生成器
public class MyGenerator : ISourceGenerator { }
#endif向后兼容策略
csharp
// 多目标框架支持
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
// 条件编译
#if NET6_0_OR_GREATER
// .NET 6+ 特性
#elif NETSTANDARD2_0
// .NET Standard 2.0 兼容代码
#endif常见问题
Q1: 应该使用哪个 API 来查找类?
A: 取决于你的需求:
- 按特性查找: 使用
ForAttributeWithMetadataName(最快) - 按语法查找: 使用
CreateSyntaxProvider - 按符号查找: 使用
Compilation.GetSymbolsWithName
Q2: 如何处理泛型类型?
A: 使用 INamedTypeSymbol 的泛型相关属性:
csharp
if (typeSymbol.IsGenericType)
{
var typeArguments = typeSymbol.TypeArguments;
var typeParameters = typeSymbol.TypeParameters;
}详见:类型系统深入
Q3: 如何生成格式化的代码?
A: 使用 NormalizeWhitespace():
csharp
var code = syntaxNode.NormalizeWhitespace().ToFullString();详见:代码生成 API
Q4: 如何报告编译错误?
A: 使用 Diagnostic.Create 和 ReportDiagnostic:
csharp
var diagnostic = Diagnostic.Create(descriptor, location, args);
context.ReportDiagnostic(diagnostic);详见:诊断 API
Q5: 如何优化生成器性能?
A: 主要策略:
- 使用增量生成器
- 缓存中间结果
- 避免重复计算
- 最小化内存分配
详见:增量生成器管道
Q6: 如何调试源生成器?
A: 几种方法:
- 使用
Debugger.Launch() - 附加到编译器进程
- 使用单元测试
- 启用生成文件输出
详见:调试和诊断
Q7: 如何处理可空引用类型?
A: 检查 NullableAnnotation:
csharp
if (typeSymbol.NullableAnnotation == NullableAnnotation.Annotated)
{
// 这是可空类型
}详见:类型系统深入
Q8: 如何跨程序集查找符号?
A: 使用 Compilation.GetTypeByMetadataName:
csharp
var type = compilation.GetTypeByMetadataName("System.String");详见:编译 API
文档更新日志
2025-01-21
- ✅ 添加完整的 API 分类说明
- ✅ 添加学习路径图
- ✅ 添加常见使用模式
- ✅ 添加性能考虑章节
- ✅ 添加版本兼容性信息
- ✅ 扩展常见问题解答
未来计划
- 📝 添加更多实际示例
- 📝 添加视频教程链接
- 📝 添加交互式示例
- 📝 添加性能基准测试结果
本文档持续更新中,欢迎反馈和建议!