五:元数据概述
前面已经知道了什么是元数据,元数据在哪个地方,以下要说的是元数据的结构。
元数据是一个二进制数据块,它由几个表构成,这些表分为三个类别:定义表(definition table)、引用表(reference table)、以及清单表(manifest table)。
常见的元数据定义表
元数据定义名称 |
说明 |
ModuleDef |
总是包含一个用于标识模块的记录项。在这个记录项中,包含模块的文件名和扩展名(但不含路径),以及一个模块的版本ID(采取由编译器创建的GUID形式),这允许自由的重命名文件,同时保留其原名称记录。然而,我们强烈反对重命名一个文件,它可能妨碍CLR在运行时正确定位一个程序集 |
TypeDef |
模块中定义的每一个类型都在这个定义表中有一个对应的记录项。每个记录项都包含类型的名称、基类型、标识以及一些索引,这些索引指向该类型在MethodDef表中拥有的该当、在FieldDef表中拥有的字段、在PropertyDef表中拥有的属性以及在EventDef表中拥有的事件 |
MethodDef |
模块中定义的每一个方法都在这个表中有一个对应的记录项。每个记录项都包含方法的名称、标识、签名、以及该方法的IL代码在模块中的偏移量。每个记录项还引用了ParamDef表的一个记录项,后者包括与方法参数有关的更多信息 |
FieldDef |
模块中定义的每一个字段都在这个表中有一个对应的记录项。每个记录项都包含标识、类型、名称 |
ParamDef |
模块中定义的每个参数都在这个定义表中有一个对应的记录项。每个记录项都包含标识、类型和名称 |
PropertyDef |
模块中定义的每一个属性都在这个定义表中有一个对应的记录项。每个记录项都包含标识、类型、和名称 |
EventDef |
模块中定义的每一个事件都在这个定义表中有一个对应的记录项。每个记录项都包含标识和名称 |
引用元数据表名称 |
说明 |
AssemblyRef |
模块中引用的每个程序集在这个表中都有一个对应的记录项。每个记录项都包含绑定到程序集所需的信息:程序集名称(不包含路径和扩展名)、版本号、语言文化以及公钥标识。每个记录项还包含 一些标识和一个哈希值。这个哈希值本来应该作为所引用的 。但是CLR目前完全忽略这个哈希值 |
ModuleRef |
实现由这个模块引用的类型的每一个PE模块在这个表中都有一个对应的记录项。每个记录项都包含都包含模块中的文件名和扩展名(不含路径)。利用这个表,可以调用程序集模块内部的不同模块中实现的类型建立绑定关系 |
TypeRef |
模块引用的每个类型在这个表中都有一个对应的记录项。每个记录项都包含类型的名称和一个引用(指向类型的位置)。如果类型是在另一个类型中实现的,那么引用的指向的就是一个TypeRef记录项。如果类型是在同一个模块中实现的,那么指向引用的就是一个ModuleDef记录项。如果类型是在调用一个程序集内容的另一个模块中实现的,那么指向引用的就是一个ModuleRef记录项。如果类型是在一个不同的程序集中实现的,那么引用指向的就是一个AssemblyRef记录项 |
MemberRef |
模块中引用的每个成员(字段和方法,以及属性方法和事件)都在这个表中有一个对应的记录项。每个记录项都包含成员的名称和签名,并引用了对成员进行定义的那个类型的TypeDef记录项 |
清单元数据表名称 |
说明 |
AssemblyDef |
如果模块代表的是一个程序集,就在这个元数据表中含有单独一个记录项。记录项列出了程序集名称(不含路径和扩展名)、版本、语言文化、一些标志、哈希算法以及发布者的公钥 |
FileDef |
作为程序集一部分的每个PE文件和资源文件在这个表中都有一个对应的记录项(包含清单的那个文件除外,因其在AssemblyDef表中显示为单一的记录项)。在每个记录项中,都包含了文件名和扩展名(不含路径)、哈希值和一些标志。如果该程序集只由它自己的文件构成,那么FileDef表中将无记录 |
ManifestResourceDef |
作为程序集一部分的每个资源在这个表中都有一个对应的记录项。记录项中包含资源名称、一些标志以及FileDef表中的一个索引。如果资源不是一个独立的文件(比如.jpg或者.gif文件)那么资源就是嵌入PE文件的一个流。如果是嵌入的资源,记录项中还包含一个偏移量,它指明了资源在PE文件中的起点 |
ExportedTypesDef |
从程序集的所有PE模块中导出的每个public类型在这个表中都有一个对应的记录项。记录项中包含类型名称。FileDef表的一个索引以及TypeDef表的一个索引。注意,为了节省文件空间,从包含清单的文件导出的类型不在这个表中重复,因为可以使用元数据的TypeDef表来攻取类型信息 |
类型成员 |
成员类型 |
对应的编程语言结构 |
AnEvent |
字段 |
事件;字段的名称是AnEvent,它的类型是System.EventHandler |
.ctor |
方法 |
构造器 |
finalize |
方法 |
终结器 |
add_AnEvent |
方法 |
事件的add访问器方法 |
get_AProperty |
方法 |
事件的get访问器方法 |
get_Item |
方法 |
索引器的get访问器方法 |
op_Addition |
方法 |
+操作符 |
op_Equality |
方法 |
==操作符 |
op_Inequality |
方法 |
!=操作符 |
remove_AnEvent |
方法 |
事件的remove访问器方法 |
set_Aproperty |
方法 |
属性的set访问器方法 |
set_Item |
方法 |
索引器的set访问器方法 |
public sealed class Program
{
public static void Main()
{
System.Console.WriteLine("Hi");
}
}
它的元数据如下: