语义模型 API:命名空间、事件和类型参数符号
📋 文档信息
难度: 🟡 中级
预计阅读时间: 25 分钟
前置知识: 语法树基础、符号系统、语义模型基础
适合人群: 中级开发者
📋 快速导航
| 章节 | 难度 | 阅读时间 | 链接 |
|---|---|---|---|
| 概览 | 🟢 | 5 分钟 | 查看 |
| 快速开始示例 | 🟢 | 10 分钟 | 查看 |
| API 速查表 | 🟢 | 5 分钟 | 查看 |
| 深入学习 | - | - | 查看 |
深入学习主题
| 主题 | 难度 | 阅读时间 | 文档链接 |
|---|---|---|---|
| 命名空间详解 | 🟢 | 30 分钟 | semantic-model-namespaces.md |
| 事件详解 | 🟢 | 25 分钟 | semantic-model-events.md |
| 类型参数详解 | 🟡 | 35 分钟 | semantic-model-type-parameters.md |
🎯 概览
本文档介绍三种重要的符号类型:命名空间符号、事件符号和类型参数符号。
INamespaceSymbol(命名空间符号):
- 表示命名空间,用于组织代码
- 提供命名空间层次结构和成员访问
- 用于代码组织分析、命名空间导入优化等
IEventSymbol(事件符号):
- 表示事件成员
- 提供事件类型、访问器(add/remove)等信息
- 用于事件处理分析、观察者模式检测等
ITypeParameterSymbol(类型参数符号):
- 表示泛型类型参数(如
T) - 提供类型参数约束、协变/逆变等信息
- 用于泛型代码分析、约束验证等
🚀 快速开始示例
csharp
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
public class QuickStartExample
{
public void AnalyzeSymbols()
{
string code = @"
namespace MyApp.Services
{
public class EventPublisher<T> where T : class
{
public event EventHandler<T> DataReceived;
}
}
";
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();
// 1. 分析命名空间
var namespaceDecl = root.DescendantNodes()
.OfType<NamespaceDeclarationSyntax>()
.First();
var namespaceSymbol = semanticModel.GetDeclaredSymbol(namespaceDecl);
Console.WriteLine($"命名空间: {namespaceSymbol.ToDisplayString()}");
// 2. 分析事件
var eventDecl = root.DescendantNodes()
.OfType<EventFieldDeclarationSyntax>()
.First();
var eventSymbol = semanticModel.GetDeclaredSymbol(
eventDecl.Declaration.Variables[0]) as IEventSymbol;
Console.WriteLine($"事件: {eventSymbol.Name}");
Console.WriteLine($"事件类型: {eventSymbol.Type.ToDisplayString()}");
// 3. 分析类型参数
var classDecl = root.DescendantNodes()
.OfType<ClassDeclarationSyntax>()
.First();
var classSymbol = semanticModel.GetDeclaredSymbol(classDecl);
foreach (var typeParam in classSymbol.TypeParameters)
{
Console.WriteLine($"类型参数: {typeParam.Name}");
if (typeParam.HasReferenceTypeConstraint)
Console.WriteLine(" 约束: class");
}
}
}📊 API 速查表
命名空间符号常用 API
| API | 说明 | 返回类型 | 示例 | 场景 |
|---|---|---|---|---|
Name | 获取命名空间名称 | string | ns.Name | 获取名称 |
ContainingNamespace | 获取父命名空间 | INamespaceSymbol | ns.ContainingNamespace | 遍历层次结构 |
GetNamespaceMembers() | 获取子命名空间 | ImmutableArray<INamespaceSymbol> | ns.GetNamespaceMembers() | 遍历子命名空间 |
GetTypeMembers() | 获取类型成员 | ImmutableArray<INamedTypeSymbol> | ns.GetTypeMembers() | 获取命名空间中的类型 |
IsGlobalNamespace | 是否是全局命名空间 | bool | ns.IsGlobalNamespace | 检查全局命名空间 |
事件符号常用 API
| API | 说明 | 返回类型 | 示例 | 场景 |
|---|---|---|---|---|
Name | 获取事件名称 | string | evt.Name | 获取名称 |
Type | 获取事件类型 | ITypeSymbol | evt.Type | 获取委托类型 |
AddMethod | 获取 add 访问器 | IMethodSymbol | evt.AddMethod | 分析事件订阅 |
RemoveMethod | 获取 remove 访问器 | IMethodSymbol | evt.RemoveMethod | 分析事件取消订阅 |
IsOverride | 是否是重写事件 | bool | evt.IsOverride | 检查事件重写 |
类型参数符号常用 API
| API | 说明 | 返回类型 | 示例 | 场景 |
|---|---|---|---|---|
Name | 获取类型参数名称 | string | tp.Name | 获取名称(如 T) |
HasReferenceTypeConstraint | 是否有 class 约束 | bool | tp.HasReferenceTypeConstraint | 检查引用类型约束 |
HasValueTypeConstraint | 是否有 struct 约束 | bool | tp.HasValueTypeConstraint | 检查值类型约束 |
HasConstructorConstraint | 是否有 new() 约束 | bool | tp.HasConstructorConstraint | 检查构造函数约束 |
ConstraintTypes | 获取类型约束 | ImmutableArray<ITypeSymbol> | tp.ConstraintTypes | 获取所有类型约束 |
Variance | 获取协变/逆变 | VarianceKind | tp.Variance | 检查协变逆变 |
🔗 深入学习
1. 命名空间详解
文档: semantic-model-namespaces.md
内容包括:
- INamespaceSymbol 核心属性
- 命名空间层次结构
- 命名空间成员访问
- 全局命名空间处理
2. 事件详解
内容包括:
- IEventSymbol 核心属性
- 事件访问器(Add/Remove)
- 事件类型和委托
- 事件重写和实现
3. 类型参数详解
文档: semantic-model-type-parameters.md
内容包括:
- ITypeParameterSymbol 核心属性
- 类型参数约束
- 泛型方法和类型
- 协变和逆变