Appearance
术语分册 3:符号与类型
这一册负责解释“类、属性、类型、编译对象”这些最常用的语义对象。
INamedTypeSymbol
关键成员:
| 成员 | 能拿到什么 |
|---|---|
Name | 类型名 |
ContainingNamespace | 所在命名空间 |
ContainingType | 外层类型,常用于嵌套类 |
IsGenericType | 是否为泛型类型 |
TypeParameters | 泛型参数集合 |
GetMembers() | 类型下的全部成员 |
最常见用途:
- 拿类名和命名空间
- 拿泛型参数
- 枚举成员后筛出属性
IPropertySymbol
- 一句话说明:表示属性这个语义成员
- 什么时候会用到:你要读取属性名、类型、访问级别、读写器时
- 对应教程:第 8 章
关键成员:
| 成员 | 能拿到什么 |
|---|---|
Name | 属性名 |
Type | 属性类型,对应 ITypeSymbol |
DeclaredAccessibility | 访问级别 |
GetMethod | getter 方法,判断能不能读 |
SetMethod | setter 方法,判断能不能写 |
ITypeSymbol
- 一句话说明:表示类型信息本身
- 什么时候会用到:你已经拿到属性、字段或表达式,准备判断类型特征
- 对应教程:第 10 章
关键成员:
| 成员 | 能拿到什么 |
|---|---|
ToDisplayString() | 适合显示或拼回源码的类型名 |
IsValueType | 是否值类型 |
NullableAnnotation | 是否带可空标注 |
OriginalDefinition | 原始泛型定义,例如 Nullable<T> |
SpecialType | 某些常见基础类型的快速分类 |
Accessibility
- 一句话说明:表示成员或类型的访问级别
- 什么时候会用到:你要筛
public属性时 - 对应教程:第 8 章
常见值:
| 成员 | 说明 |
|---|---|
Accessibility.Public | 公共可见 |
Accessibility.Private | 私有 |
Accessibility.Internal | 程序集内可见 |
NullableAnnotation
- 一句话说明:表示类型有没有可空标注
- 什么时候会用到:你要区分
string、string?、int? - 对应教程:第 10 章
常见值:
| 成员 | 说明 |
|---|---|
None | 没有可空上下文信息 |
NotAnnotated | 未标注可空 |
Annotated | 已标注可空 |
SpecialType
- 一句话说明:用于识别某些常见内置类型
- 什么时候会用到:你要精确判断
string、int、object、Nullable<T>的某些场景 - 对应教程:第 10 章
Compilation
- 一句话说明:表示一次完整编译
- 什么时候会用到:你要查看全部语法树、全局诊断、根命名空间,或按全名找类型
- 对应教程:第 12 章
关键成员:
| 成员 | 能拿到什么 |
|---|---|
SyntaxTrees | 当前编译中的所有语法树 |
GetDiagnostics() | 当前编译的诊断 |
GlobalNamespace | 根命名空间入口 |
GetTypeByMetadataName(...) | 按元数据全名找类型 |
GlobalNamespace
- 一句话说明:整个编译的根命名空间入口
- 什么时候会用到:你要从顶层往下找命名空间或类型时
- 对应教程:第 12 章
CompilationProvider
- 一句话说明:把整个
Compilation作为增量输入接进管道 - 什么时候会用到:你需要同时读取“目标节点 + 整个编译”时
源码入口:
sample/05-dto-mapper-generator/DtoMapperGenerator/DtoMapperGenerator.cs
关键片段:
csharp
var combined = context.CompilationProvider
.Combine(mapFromClasses)
.Combine(mapToClasses);为什么看它:
CompilationProvider自己不做筛选,它提供的是“整个编译上下文”- 当你要同时读取目标节点和全局语义信息时,通常会和
Combine(...)一起出现 sample/05很适合理解这一点,因为它需要跨类型做 DTO 映射分析
IsGlobalNamespace
- 一句话说明:判断当前命名空间是不是全局命名空间
- 什么时候会用到:你要决定是否生成
namespace ...包裹时
最常见的组合查询
| 我想拿什么 | 典型链路 |
|---|---|
| 类名、命名空间 | INamedTypeSymbol.Name + ContainingNamespace |
| 属性列表 | INamedTypeSymbol.GetMembers() + OfType<IPropertySymbol>() |
| 属性类型显示名 | IPropertySymbol.Type.ToDisplayString() |
| 是否值类型 | IPropertySymbol.Type.IsValueType |
| 是否可空 | IPropertySymbol.Type.NullableAnnotation |
| 整个编译有哪些树 | Compilation.SyntaxTrees |
下一步去哪里
- 想读特性参数和泛型约束:看 术语分册 4:特性与泛型
- 想读测试里的编译构造:看 术语分册 5:编译与测试
- 返回索引:看 术语与 API 手册