元数据

什么是元数据?

元数据是描述数据(类型信息)的数据,是有一组数据表构成的一个二进制数据块。元数据被CLR编译器编译后保存在Windows可移植执行体(PE)文件中,即和它描述的IL嵌入在EXE/DLL文件中。

怎么查看托管代码的元数据?

使用ildasm.exe打开EXE/DLL文件,并按Ctrl+M组合键或执行视图/元信息/显示将发现有关类型元数据。

元数据都有那些数据表构成?

元数据主要的类型表:

  • 定义表 描述当前程序集中定义的类型和成员信息 主要包括:TypeDef、MehodDef、FieldDef、ModuleDef、PropertyDef等。
  • 引用表 描述任何一个被内部类型引用的外部的类型和成员信息,引用元素可以是同一程序集的其他模块,也可以是不同程序集的模块 主要包括:AssemblyRef、TypeRef、ModuleRef、MethodsRef等。
  • 清单表 描述了构成程序集的所有文件
  • 指针表 使用指针表引用未知代码,主要包括:MethodPtr、FieldPtr、ParamPtr等。
  • 堆       以stream的形式保存的信息堆,主要包括:#String、#Blob、#US、#GUIDe等。

 

在.NET中每个模块包含了44个CLR元数据表,如下:

表记录 元数据表 说明
0(0) ModuleDef 描述当前模块
1(0x1) TypeRef 描述引用Type,为每个引用到类型保存一条记录
2(0x2) TypeDef 描述Type定义,每个Type将在TypeDef表中保存一条记录
3(0x3) FieldPtr 描述字段指针,定义类的字段时的中间查找表
4(0x4) FieldDef 描述字段定义
5(0x5) MethodPtr 描述方法指针,定义类的方法时的中间查找表
6(0x6) MethodDef 描述方法定义
7(0x7) ParamPtr 描述参数指针,定义类的参数时的中间查找表
8(0x8) ParamDef 描述方法的参数定义
9(0x9) InterfaceImpl 描述有哪些类型实现了哪些接口
10(0xa) MemberRef 描述引用成员的情况,引用成员可以是方法、字段还有属性。
11(0xb) Constant 描述了参数、字段和属性的常数值
12(0xc) CustomAttribute 描述了特性的定义
13(0xd) FieldMarshal 描述了与非托管代码交互时,参数和字段的传递方式。
14(0xe) DeclSecurity 描述了对于类、方法和程序集的安全性
15(0xf) ClassLayout 描述类加载时的布局信息
16(0x10) FieldLayout 描述单个字段的偏移或序号
17(0x11) StandAloneSig 描述未被任何其他表引用的签名
18(0x12) EventMap 描述类的事件列表
19(0x13) EventPtr 描述了事件指针,定义事件时的中间查找表
20(0x14) Event                描述事件
21(0x15) PropertyMap          描述类的属性列表
22(0x16) PropertyPtr          描述了属性指针,定义类的属性时的中间查找表
23(0x17) Property             描述属性
24(0x18) MethodSemantics      描述事件、属性与方法的关联
25(0x19) MethodImpl           描述方法的实现
26(0x1a) ModuleRef            描述外部模块的引用
27(0x1b) TypeSpec             描述了对TypeDef或者TypeRef的说明
28(0x1c) ImplMap              描述了程序集使用的所有非托管代码的方法
29(0x1d) FieldRVA             字段表的扩展,RVA给出了一个字段的原始值位置
30(0x1e) ENCLog               描述在Edit-And-Continue模式中哪些元数据被修改过
31(0x1f) ENCMap               描述在Edit-And-Continue模式中的映射
32(0x20) Assembly             描述程序集定义
33(0x21) AssemblyProcessor    未使用
34(0x22) AssemblyOS           未使用
35(0x23) AssemblyRef          描述引用的程序集
36(0x24) AssemblyRefProcessor 未使用
37(0x25) AssemblyRefOS        未使用
38(0x26) File                 描述外部文件
39(0x27) ExportedType         描述在同一程序集但不同模块,有哪些类型
40(0x28) ManifestResource     描述资源信息
41(0x29) NestedClass          描述嵌套类型定义
42(0x2a) GenericParam         描述了泛型类型定义或者泛型方法定义所使用的泛型参数
43(0x2b) MethodSpec           描述泛型方法的实例化
44(0x2c) GenericParamConstraint 描述了每个泛型参数的约束

然后是6个命名堆:

说明

#String 一个AscII string数组,被元数据表所引用,来表示方法名、字段名、类名、变量名以及资源相关字符串,但不包含string literals。
#Blob 包含元数据引用的二进制对象,但不包含用户定义对象
#User Strings 记录字符串字面量 一个unicode string数组,包含了定义在代码中的字符串(string literals),这些字符串可以直接由ldstr指令加载获取,还记得吗?我们在《第二十二回:字符串驻留(上)---带着问题思考》中对字符串创建过程的论述吗?
#GUID 保存了128byte的GUID值,由元数据表引用
#~ 一个特殊堆,包含了所有的元数据表,会引用其他的堆。
#- 一个未压缩的#~堆。除了#-堆,其他堆都是压缩的。

Note:对于#String和#User Strings,一个简单的区别就是:string hello = "Hello, World";变量hello名,将保存在#String,而代码中字符串信息“Hello, World”则被保存在#US中。

元数据的用途

  • 编译时,元数据消除了对本地C/C++头和库文件的需求,因为在负责在实现类型/成员的IL代码文件中,已包含和引用的类型/成员有关的全部信息。编译器可以直接从托管模块读取元数据。
  • VS使用元数据帮助您写代码。它的“智能感知”(IntelliSense)技术可以解析元数据,指出一个类型提供了哪些方法、属性、事件和字段。
  • 许多.NET技术,如对象序列化、.NET远程处理、XML WEB服务、以及WCF都需要元数据在运行时发现类型格式。
  • 元数据允许垃圾回收器跟踪对象的生存期。垃圾回收器能判断任何对象的类型,并从元数据知道那个对象中的哪些字段引用了其它对象。

 参考文章: [你必须知道的.NET]第二十五回:认识元数据和IL(中)

 

作者:代码哥
出处:http://daimage.cnblogs.com/
说明:本博原创文章版权归博客园和本人共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出作者名称和原文连接,否则保留追究法律责任的权利。

posted @ 2012-02-05 20:22  代码哥  阅读(1867)  评论(0编辑  收藏  举报