Skip to content

Roslyn API 完整参考文档

深入、全面的 Roslyn 源生成器 API 参考指南

📚 文档结构

本 API 参考文档分为多个独立的章节,每个章节深入讲解 Roslyn API 的特定领域。

核心文档

  1. 语义模型 API

    • 符号系统详解
    • 类型系统深入
    • 特性处理
    • 符号比较和等价性
    • 类型转换和兼容性
  2. 编译 API

    • 编译创建和配置
    • 元数据引用管理
    • 程序集加载和解析
    • 跨程序集符号查找
    • 编译选项和优化
  3. 代码生成 API

    • SyntaxFactory 完整指南
    • 代码构建模式
    • 格式化和美化
    • 复杂结构生成
    • 字符串插值 vs SyntaxFactory
  4. 诊断 API

    • 诊断描述符设计
    • 诊断报告策略
    • 严重级别选择
    • 位置和范围
    • 诊断抑制
  5. 增量生成器管道

    • 管道操作详解
    • 数据流转换
    • 缓存机制
    • 性能优化
    • 调试管道
  6. 类型系统深入

    • 类型层次结构
    • 泛型类型处理
    • 可空类型
    • 数组和集合类型
    • 特殊类型
  7. 表达式和语句 API

    • 表达式语法节点
    • 语句语法节点
    • 控制流分析
    • 数据流分析
  8. 高级技巧和模式

    • 性能优化技巧
    • 内存管理
    • 并发处理
    • 错误处理模式
    • 测试策略

实用指南

  1. 常见场景实现

    • 序列化生成器
    • ORM 映射生成器
    • 依赖注入生成器
    • 日志生成器
    • API 客户端生成器
  2. 调试和诊断

    • 调试生成器
    • 性能分析
    • 常见错误
    • 故障排除
  3. 最佳实践

    • 代码组织
    • 命名约定
    • 错误处理
    • 性能考虑
    • 可维护性
  4. 反模式和陷阱

    • 常见错误
    • 性能陷阱
    • 内存泄漏
    • 线程安全问题

🎯 快速导航

按任务查找

按 API 类型查找


📖 阅读建议

初学者路径

  1. 先阅读 LEARNING_GUIDE.md 了解基础
  2. 阅读 语义模型 API 理解符号系统
  3. 阅读 代码生成 API 学习如何生成代码
  4. 阅读 常见场景实现 看实际例子

进阶路径

  1. 阅读 增量生成器管道 优化性能
  2. 阅读 类型系统深入 处理复杂类型
  3. 阅读 高级技巧和模式 学习最佳实践
  4. 阅读 调试和诊断 解决问题

问题解决路径

遇到问题时:

  1. 查看 反模式和陷阱 看是否是常见错误
  2. 查看 调试和诊断 学习调试方法
  3. 查看 最佳实践 了解正确做法

🔗 相关资源


📝 文档约定

代码示例

所有代码示例都包含:

  • ✅ 完整的代码(可以直接运行)
  • ✅ 详细的中文注释
  • ✅ 输入和输出示例
  • ✅ 常见错误和解决方案

图表

使用 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.03.8+源生成器 v1
.NET 6.04.0+增量生成器
.NET 7.04.3+性能改进
.NET 8.04.8+新的 API
.NET 9.04.11+更多优化
.NET 10.04.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.CreateReportDiagnostic:

csharp
var diagnostic = Diagnostic.Create(descriptor, location, args);
context.ReportDiagnostic(diagnostic);

详见:诊断 API

Q5: 如何优化生成器性能?

A: 主要策略:

  1. 使用增量生成器
  2. 缓存中间结果
  3. 避免重复计算
  4. 最小化内存分配

详见:增量生成器管道

Q6: 如何调试源生成器?

A: 几种方法:

  1. 使用 Debugger.Launch()
  2. 附加到编译器进程
  3. 使用单元测试
  4. 启用生成文件输出

详见:调试和诊断

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 分类说明
  • ✅ 添加学习路径图
  • ✅ 添加常见使用模式
  • ✅ 添加性能考虑章节
  • ✅ 添加版本兼容性信息
  • ✅ 扩展常见问题解答

未来计划

  • 📝 添加更多实际示例
  • 📝 添加视频教程链接
  • 📝 添加交互式示例
  • 📝 添加性能基准测试结果

本文档持续更新中,欢迎反馈和建议!

基于 MIT 许可发布