Skip to content

语义模型 API:类型和方法符号

📋 文档信息

难度: 🟡 中级
预计阅读时间: 30 分钟
前置知识: 语法树基础、符号系统、语义模型基础
适合人群: 中级开发者,需要深入理解类型和方法分析


📋 快速导航

章节难度阅读时间链接
概览🟢5 分钟查看
快速开始示例🟢10 分钟查看
API 速查表🟢5 分钟查看
深入学习--查看

深入学习主题

主题难度阅读时间文档链接
类型系统详解🟡45 分钟semantic-model-types.md
方法分析详解🟡45 分钟semantic-model-methods.md
实战示例和最佳实践🟡40 分钟semantic-model-type-examples.md

🎯 概览

在 Roslyn 中,符号(Symbol) 是对代码元素的语义表示。类型符号和方法符号是最常用的两种符号:

INamedTypeSymbol(命名类型符号)

  • 表示类、结构、接口、枚举、委托、记录等命名类型
  • 提供类型的完整元数据:继承关系、成员、泛型参数等
  • 用于类型分析、代码生成、重构工具等

IMethodSymbol(方法符号)

  • 表示方法、构造函数、析构函数、运算符等
  • 提供方法签名、参数、返回值、重载信息等
  • 用于方法调用分析、参数验证、代码生成等

典型应用场景

  • 生成 DTO 映射代码(需要分析类型的属性)
  • 实现依赖注入容器(需要分析构造函数参数)
  • 创建序列化器(需要分析类型成员)
  • 实现代码分析器(需要检查方法调用)

三种节点类型对比

特性语法节点 (Syntax)符号 (Symbol)语义模型 (SemanticModel)
表示内容代码的语法结构代码的语义含义连接语法和符号的桥梁
包含信息标识符、关键字、位置类型、成员、继承关系类型推断、符号查找
使用场景代码格式化、语法分析类型分析、代码生成获取符号、类型检查
示例ClassDeclarationSyntaxINamedTypeSymbolGetDeclaredSymbol()

🚀 快速开始示例

让我们看一个完整的例子,了解如何获取和使用类型和方法符号:

csharp
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

public class QuickStartExample
{
    public void AnalyzeTypeAndMethod()
    {
        // 步骤 1:准备代码
        string code = @"
            public class UserService
            {
                public User GetUser(int id)
                {
                    return new User { Id = id };
                }
            }
            
            public class User
            {
                public int Id { get; set; }
                public string Name { get; set; }
            }
        ";
        
        // 步骤 2:创建语法树和编译
        var syntaxTree = CSharpSyntaxTree.ParseText(code);
        var compilation = CSharpCompilation.Create("QuickStart")
            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
            .AddSyntaxTrees(syntaxTree);
        
        var semanticModel = compilation.GetSemanticModel(syntaxTree);
        var root = syntaxTree.GetRoot();
        
        // 步骤 3:获取类型符号
        var userClass = root.DescendantNodes()
            .OfType<ClassDeclarationSyntax>()
            .First(c => c.Identifier.Text == "User");
        
        var userTypeSymbol = semanticModel.GetDeclaredSymbol(userClass) as INamedTypeSymbol;
        
        Console.WriteLine($"类型名称: {userTypeSymbol.Name}");
        Console.WriteLine($"类型种类: {userTypeSymbol.TypeKind}");
        Console.WriteLine($"是否是引用类型: {userTypeSymbol.IsReferenceType}");
        
        // 步骤 4:获取方法符号
        var getUserMethod = root.DescendantNodes()
            .OfType<MethodDeclarationSyntax>()
            .First(m => m.Identifier.Text == "GetUser");
        
        var methodSymbol = semanticModel.GetDeclaredSymbol(getUserMethod) as IMethodSymbol;
        
        Console.WriteLine($"方法名称: {methodSymbol.Name}");
        Console.WriteLine($"返回类型: {methodSymbol.ReturnType.Name}");
        Console.WriteLine($"参数数量: {methodSymbol.Parameters.Length}");
    }
}

提示

使用 GetDeclaredSymbol() 从语法节点获取符号,使用 GetSymbolInfo() 从表达式获取符号。


📊 API 速查表

类型符号常用 API

API说明返回类型示例场景
Name获取类型名称stringtypeSymbol.Name获取类型名称
TypeKind获取类型种类TypeKindtypeSymbol.TypeKind判断是类/接口/结构
BaseType获取基类INamedTypeSymboltypeSymbol.BaseType分析继承关系
Interfaces获取实现的接口ImmutableArray<INamedTypeSymbol>typeSymbol.Interfaces分析接口实现
GetMembers()获取所有成员ImmutableArray<ISymbol>typeSymbol.GetMembers()遍历类型成员
IsGenericType是否是泛型类型booltypeSymbol.IsGenericType检查泛型
TypeParameters获取类型参数ImmutableArray<ITypeParameterSymbol>typeSymbol.TypeParameters分析泛型参数
IsReferenceType是否是引用类型booltypeSymbol.IsReferenceType判断类型类别
IsValueType是否是值类型booltypeSymbol.IsValueType判断类型类别
IsRecord是否是记录类型booltypeSymbol.IsRecord检查记录类型

方法符号常用 API

API说明返回类型示例场景
Name获取方法名称stringmethodSymbol.Name获取方法名称
ReturnType获取返回类型ITypeSymbolmethodSymbol.ReturnType分析返回值
Parameters获取参数列表ImmutableArray<IParameterSymbol>methodSymbol.Parameters分析参数
IsAsync是否是异步方法boolmethodSymbol.IsAsync检查异步方法
IsExtensionMethod是否是扩展方法boolmethodSymbol.IsExtensionMethod检查扩展方法
IsGenericMethod是否是泛型方法boolmethodSymbol.IsGenericMethod检查泛型方法
MethodKind获取方法种类MethodKindmethodSymbol.MethodKind判断方法类型
OverriddenMethod获取被重写的方法IMethodSymbolmethodSymbol.OverriddenMethod分析方法重写
IsVirtual是否是虚方法boolmethodSymbol.IsVirtual检查虚方法
IsOverride是否是重写方法boolmethodSymbol.IsOverride检查重写

🔗 深入学习

本文档提供了类型和方法符号的概览和快速入门。要深入学习,请参阅以下专题文档:

1. 类型系统详解

文档: semantic-model-types.md

内容包括

  • INamedTypeSymbol 核心属性详解
  • 泛型类型处理(开放泛型、封闭泛型、类型参数)
  • 继承和接口(基类访问、接口实现、继承链遍历)
  • 特殊类型处理(枚举、委托、记录、元组)

适合场景

  • 需要深入分析类型结构
  • 处理复杂的泛型类型
  • 分析类型继承关系
  • 生成类型相关的代码

2. 方法分析详解

文档: semantic-model-methods.md

内容包括

  • IMethodSymbol 核心属性详解
  • 方法签名分析
  • 参数和返回值处理
  • 方法重载和重写
  • 扩展方法和泛型方法

适合场景

  • 需要分析方法调用
  • 处理方法重载和重写
  • 分析方法参数
  • 生成方法相关的代码

3. 实战示例和最佳实践

文档: semantic-model-type-examples.md

内容包括

  • 完整的类型分析器示例
  • 真实使用场景(查找派生类、分析接口实现、生成代码)
  • 最佳实践(符号比较、泛型处理、null 检查等)
  • 反模式和陷阱(常见错误及解决方案)
  • 高级主题和可视化图表

适合场景

  • 学习完整的实战案例
  • 了解最佳实践
  • 避免常见错误
  • 理解复杂的类型关系

📚 相关资源

API 参考文档

相关文档

其他语义模型文档


📚 下一步

基于 MIT 许可发布