1.元数据简介

全称:metadata

属性:数据表集合

产地:面向 CLR 的编译器在托管模块中生成

2.元数据内部结构及与托管模块的关系

【概述】

托管模块中包含着元数据,元数据是由一组数据表组成的。其中一些数据表描述了模块中定义的内容

【关系图】

3.元数据的用途

  • 编译时,元数据消除了对本地 C/C++ 头和库文件的需求,因为在负责实现类型/成员的 IL 代码文件中,已包含和引用的类型/成员有关的全部信息。编译器可直接从托管模块读取元数据。
  • Microsoft Visual Studio 使用元数据帮助你写代码。它的“智能感知”(IntelliSense)技术可以解析元数据,指出一个类型提供了哪些方法、属性、事件和字段。如果是一个方法,还能指出该方法需要什么参数。
  • CLR 的代码验证过程使用元数据确保代码只执行“类型安全”的操作。
  • 元数据允许将一个对象的字段序列化到一个内存块中,将其发送给另一台机器,然后反序列化,在远程机器上重建对象的状态。
  • 元数据允许垃圾回收期跟踪对象的生存期。垃圾回收器能判断任何对象的类型,并从元数据知道哪个对象中的哪些字段引用了其他对象。

4.第二章元数据内容

元数据是一个二进制数据块,由几个表构成。这些表分为三个类别:定义表(definition table)、引用表(reference table)和清单表(manifest table)。

【常用的定义表】

  • ModuleDef

总是包含一个用于标识模块的记录项。在这个记录项中,包含模块的文件名和扩展名(不含路径),以及一个模块版本ID(采用由编译器创建的GUID的形式)。这允许自由地重命名文件,同事保留其原始名称记录。然而,不建议重命名,它会妨碍CLR在运行时正确定位程序集。

  • TypeDef

  模块中定义的每个类型都在这个定义表中有一个对应的记录项。每个记录项都包含类型的名称、基类型、一些标志(public、private等)以及一些索引,这些索引指向该类型在MethodDef表中拥有的方法、在FieldDef表中拥有的字段、在PropertyDef表中拥有的属性以及在EventDef表中拥有的事件。

  • MethodDef

  模块中定义的每个方法都在这个定义表中有一个对应的记录项。每个记录项都包含方法的名称、一些标志(private、public、virtual、abstract、static、final等)、签名以及该方法的IL代码在模块中的偏移量。每个记录项还引用了ParamDef表中的一个记录项,后者包括与方法参数相关的更多信息。

  • FieldDef

  模块中定义的每个字段都在这个定义表中有一个对应的记录项。每个记录项包括标志(public、private等)、类型和名称。

  • ParamDef

  模块中定义的每个参数都在这个定义表中有一个对应的记录项。每个记录项都包含标志(in,out,retval等)、类型和名称。

  • PropertyDef

  模块中定义的每个属性都在这个定义表中有一个对应的记录项。每个记录项都包含标志、类型和名称。

  • EventDef

  模块中定义的每个事件都在这个定义表中有一个对应的记录项。每个记录项都包含标志和名称。

【常用的引用表】

  • AssemblyRef

  模块中引用的每个程序集在这个表中都有一个对应的记录项。每个记录项都包含绑定到程序集所需的信息:程序集名称(不含路径和扩展名)、版本号、语言文化(culture)以及公钥标记(根据发布者的公钥生成的一个小的哈希值,它标识了所引用的程序集的发布者)。在每个记录项中,还包含一些标志(flag)和一个哈希值。这个哈希值本应作为所引用的程序集的二进制数据的一个校验和来使用。但是,目前的CLR完全忽略这个哈希值,未来的CLR可能同样如此。

  • ModuleRef

  当前模块引用的类型可能是由别的PE模块实现的,所有那些模块在这个表中都有一个对应的记录项。每个记录项都包含模块的文件名和扩展名(不含路径)。在当前的调用程序集中,可能是别的模块实现了你需要的类型,这个表的作用便是建立同那些类型的绑定关系。

  • TypeRef

  模块引用的每个类型在这个表中都有一个对应的记录项。每个记录项都包含类型的名称和一个引用(指向类型的位置)。如果类型是在另一类型中实现的,引用指向的就是一个TypeRef记录项。如果类型是在同一个模块中实现的,引用指向的就是一个ModuleDef记录项。如果类型是在调用程序集内部的另一个模块中实现的,引用指向的就是一个ModuleRef记录项。如果类型是在不同的程序集中实现的,引用指向的就是一个AssemblyRef记录项。

  • MemeberRef

  模块引用的每个成员(字段、方法,以及属性方法和事件方法)都在这个表中有一个对应的记录项。每个记录项都包含成员的名称和签名,并指向对成员进行定义的那个类型的TypeRef记录项。

【常用清单表】

  • AssemblyDef

  如果该模块标识的是一个程序集,就在这个元数据表中包含单个记录项。该记录项列出了程序集名称(不含路径和扩展名)、版本(major,minor,build和revision)、语言文化(culture)、一些标志(flag)、哈希算法以及发布者的公钥(可为null)

  • FileDef

  作为程序集一部分的每个PE文件和资源文件在这个表中都有一个对应的记录项(包含清单本身的那个文件除外,它在AssemblyDef表中显示为单一记录项)。在每个记录相中,都包含文件名和扩展名(不含路径)、哈希值和一些标志(flags)。假如该程序集只包含它自己的文件,FileDef表中将无记录项。

  • ManifestResourceDef

  作为程序集一部分的每个资源在这个表中都有一个对应的记录项。记录项中包含资源的名称、一些标志(如果程序集外部可见,就为public;否则为private)以及FileDef表的一个索引(指出资源包含在哪个文件中)。如果资源不是一个独立文件(比如.jpg或者.gif文件),那么资源就是包含在PE文件中的一个流。对于嵌入的资源,这个记录项还包含一个偏移量,指出了资源流在PE文件中的起始位置。

  • ExportedTypesDef

  从程序集的所有PE模块中导出的每个public类型在这个表中都有一个对应的记录项。记录项中包含类型的名称、FileDef表的一个索引(指出类型是由该程序集的哪个文件实现的)以及TypeDef表的一个索引。注意,为了节省文件空间,从包含清单的文件导出的类型不在这个表中重复,以为可以使用元数据的TypeDef表来获取类型信息。

读经典——《CLR via C#》(Jeffrey Richter著) 笔记_元数据的更多相关文章

  1. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_发布者策略控制

    在 读经典——<CLR via C#>(Jeffrey Richter著) 笔记_高级管理控制(配置)中,是由程序集的发布者将程序集的一个新版本发送给管理员,后者安装程序集,并手动编辑应用 ...

  2. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_通过ILDasm.exe查看编译器如何将类型及其成员编译成元数据

    [实例代码] using System; public sealed class SomeType //-------------1 { //嵌套类 private class SomeNestedT ...

  3. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_基元类型(二)

    [基元类型推荐] 推荐直接使用 FCL 类型. [理由] 编码时不至于困惑string与String的使用.由于C#的stirng(一个关键字)直接映射到System.String(一个 FCL 类型 ...

  4. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_基元类型(一)

    [概念] 编译器直接支持的数据类型 [C#基元类型与对应的 FCL 类型] C#基元类型 FCL 类型 说明 sbyte System.Sbyte 有符号8位值 byte System.Byte 无符 ...

  5. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_高级管理控制(配置)

    一个应用程序的XML配置文件示例: <?xml version="1.0"?> <configuration> <runtime> <as ...

  6. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_运行时解析类型引用

    public sealed class Program{ public static void Main() { System.Console.WriteLine("Hi"); } ...

  7. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_方法执行

    [前言] 方法执行前,CLR 会检测方法内代码引用的所有类型.同时 CLR 会分配一个内部数据结构,用来管理对所有引用的类型的访问. 首次执行方法时,托管程序集会把 IL 转换成本地 CPU 指令,并 ...

  8. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_友元程序集

    [应用场景] 程序集A访问程序集B定义的Internal访问类型的类的成员. [使用方式] 在构建程序集B的时候,引入System.Runtime.CompilerServices,以此来添加Inte ...

  9. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_类型的各种成员

    [Class中,可能包含的成员] 常量, 字段, 实例构造器, 类型构造器, 方法, 操作符重载, 转换操作符, 属性, 事件, 类型(Class)

随机推荐

  1. Android添加Menu菜单

    在安卓中添加Menu菜单十分简单. 步骤: 1.在menu文件夹中的main.xml文件中添加要添加的项目. <menu xmlns:android="http://schemas.a ...

  2. DHCP工作工程

    1.客户端请求IP 客户端发一个DHCP DISCOVEY(包含主机名.mac地址)广播包 2.服务端响应请求 DHCP服务器收到请求后,查看自己的地址池是否有合法的地址.如果有,广播一个DHCP o ...

  3. cookie禁用后的session

    在浏览器地址后加:jsessionid="对应的32位字符串",照样可以访问. 在用户角度来说,浏览器开启,关闭就是一次会话. 在服务器角度来说,session失效才代表一次会话的 ...

  4. ava的打包jar、war、ear包的作用、区别、打包方式

    编为大家介绍,基于Java的打包jar.war.ear包的作用与区别详解.需要的朋友参考下以最终客户的角度来看,JAR文件就是一种封装,他们不需要知道jar文件中有多少个.class文件,每个文件中的 ...

  5. wpf textblock超出显示范围后显示tooltip

    public static class TextTrmmingShowToolTip { public static readonly DependencyProperty IsToolTipProp ...

  6. 718C Sasha and Array

    传送门 题目 Sasha has an array of integers a1, a2, ..., an. You have to perform m queries. There might be ...

  7. windows平台下用C#访问HBase

    Hadoop中的HBase有多种数据访问方式,ubuntu里可以用hbase shell查看操作hbase数据库,但windows平台下需要用thrift对它进行访问. 例如hadoop安装在/usr ...

  8. CLRInjection - 通用托管注入(超级灰色按钮克星升级版)

    通用托管注入 - CLRInjection CLR软件系列第二发: 通用托管注入 - CLRInjection 软件简介:这款软件可以将任意托管DLL用插件的形式,注入到正在运行中的.net托管程序集 ...

  9. 把Spark SQL的metadata存储到mysql

    1:安装配置mysql yum install mysql mysql-server service mysqld start mysqladmin -u root  password newpass ...

  10. 《Maven实战》笔记-1-Maven使用入门

    <Maven实战>徐晓斌 2011 机械工业出版社   一.介绍 1.名词 artifact:插件 极限编程XP 2.构建脚本: maven——pom.xml(Project Object ...