元数据概述:元数据是一种二进制信息,用以对存储在公共语言运行库可移植可执行文件 (PE) 文件或存储在内存中的程序进行描述。将您的代码编译为 PE 文件时,便会将元数据插入到该文件的一部分中,而将代码转换为 Microsoft 中间语言 (MSIL) 并将其插入到该文件的另一部分中。在模块或程序集中定义和引用的每个类型和成员都将在元数据中进行说明。当执行代码时,运行库将元数据加载到内存中,并引用它来发现有关代码的类、成员、继承等信息。

元数据以非特定语言的方式描述在代码中定义的每一类型和成员。元数据存储以下信息:

  • 程序集的说明。

    • 标识(名称、版本、区域性、公钥)。

    • 导出的类型。

    • 该程序集所依赖的其他程序集。

    • 运行所需的安全权限。

  • 类型的说明。

    • 名称、可见性、基类和实现的接口。

    • 成员(方法、字段、属性、事件、嵌套的类型)。

  • 属性。

    • 修饰类型和成员的其他说明性元素。

元数据的优点

对于一种更简单的编程模型来说,元数据是关键,该模型不再需要接口定义语言 (IDL) 文件、头文件或任何外部组件引用方法。元数据允许 .NET 语言自动以非特定语言的方式对其自身进行描述,而这是开发人员和用户都无法看见的。另外,通过使用属性,可以对元数据进行扩展。元数据具有以下主要优点:

  • 自描述文件

    公共语言运行库模块和程序集是自描述的。模块的元数据包含与另一个模块进行交互所需的全部信息。元数据自动提供 COM 中 IDL 的功能,允许将一个文件同时用于定义和实现。运行库模块和程序集甚至不需要向操作系统注册。结果,运行库使用的说明始终反映编译文件中的实际代码,从而提高应用程序的可靠性。

  • 语言互用性和更简单的基于组件的设计

    元数据提供所有必需的有关已编译代码的信息,以供您从用不同语言编写的 PE 文件中继承类。您可以创建用任何托管语言(任何面向公共语言运行库的语言)编写的任何类的实例,而不用担心显式封送处理或使用自定义的互用代码。

  • 属性

    .NET Framework 允许您在编译文件中声明特定种类的元数据(称为属性)。在整个 .NET Framework 中到处都可以发现属性的存在,属性用于更精确地控制运行时您的程序如何工作。另外,您可以通过用户定义的自定义属性向 .NET Framework 文件发出您自己的自定义元数据。有关更多信息,请参见利用属性扩展。

元数据和PE文件结构:

元数据存储在 .NET Framework 可移植可执行文件 (PE) 文件的一个部分中,而 Microsoft 中间语言 (MSIL) 则存储在 PE 文件的另一部分中。文件的元数据部分包含一系列的表和堆数据结构。MSIL 部分包含 MSIL 和引用 PE 文件元数据部分的元数据标记。当使用工具(例如,使用 MSIL 反汇编程序 (Ildasm.exe) 来查看代码的 MSIL 或使用运行库调试器 (Cordbg.exe) 来执行内存转储)时,您可能会遇到元数据标记。

元数据表和堆

每个元数据表都保留有关程序元素的信息。例如,一个元数据表说明代码中的类,另一个元数据表说明字段等。如果您的代码中有 10 个类,类表将有 10 行,每行一类。元数据表引用其他的表和堆。例如,类的元数据表引用方法表。

元数据还以四种堆结构存储信息:字符串、Blob、用户字符串和 GUID。所有用于对类型和成员进行命名的字符串都存储在字符串堆中。例如,方法表不直接存储特定方法的名称,而是指向存储在字符串堆中的方法的名称。

元数据标记

元数据标记在 PE 文件的 MSIL 部分中唯一确定每个元数据表的每一行。元数据标记在概念上和指针相似,永久驻留在 MSIL 中,引用特定的元数据表。

元数据标记是一个四个字节的数字。最高位字节表示特定标记(方法、类型等)引用的元数据表。剩下的三个字节指定与所说明的编程元素对应的元数据表中的行。如果您用 C# 定义一个方法并将其编译到 PE 文件,下面的元数据标记可能存在于 PE 文件的 MSIL 部分:

   
0x06000004

其中最高位字节 (0x06) 表示这是一个 MethodDef 标记。低位的三个字节 (000004) 指示公共语言运行库在MethodDef 表的第四行查找对该方法定义进行描述的信息。

PE 文件中的元数据

当为公共语言运行库编译程序时,该程序转换为由三部分组成的 PE 文件。下表说明了每部分的内容。

PE部分

PE 部分的内容

PE 标头

PE 文件主要部分的索引和入口点的地址。

运行库使用该信息确定该文件为 PE 文件并确定当将程序加载到内存时执行从何处开始。

MSIL 指令

组成代码的 Microsoft 中间语言指令 (MSIL)。许多 MSIL 指令带有元数据标记。

元数据

元数据表和堆。运行库使用该部分记录您的代码中每个类型和成员的信息。本部分还包括自定义属性和安全性信息。

元数据在运行时的作用:

要更好地理解元数据和它在公共语言运行库中的作用,构造一个简单的程序并说明元数据如何影响它的运行时情况可能很有帮助。下面的代码示例显示名为 MyApp 的类中的两种方法。Main 方法是程序入口点,而 Add 方法只返回两个整数参数的和。

  1. using System;
  2. public class MyApp
  3. {
  4. public static int Main()
  5. {
  6. int ValueOne = 10;
  7. int ValueTwo = 20;
  8. Console.WriteLine("The Value is: {0}", Add(ValueOne, ValueTwo));
  9. return 0;
  10. }
  11. public static int Add(int One, int Two)
  12. {
  13. return (One + Two);
  14. }
  15. }

当代码运行时,运行库将模块加载到内存并向元数据咨询该类的信息。加载后,运行库对方法的 Microsoft 中间语言 (MSIL) 流执行广泛的分析,将其转换为快速本机指令。运行库根据需要使用实时 (JIT) 编译器将 MSIL 指令转换为本机代码,每次转换一个方法。

下面的示例显示了从以前代码的 Main 功能生成的部分 MSIL。您可以使用 MSIL 反汇编程序 (Ildasm.exe) 从任何 .NET Framework 应用程序中查看 MSIL 和元数据。

  1. .entrypoint
  2. .maxstack  3
  3. .locals ([0] int32 ValueOne,
  4. [1] int32 ValueTwo,
  5. [2] int32 V_2,
  6. [3] int32 V_3)
  7. IL_0000:  ldc.i4.s   10
  8. IL_0002:  stloc.0
  9. IL_0003:  ldc.i4.s   20
  10. IL_0005:  stloc.1
  11. IL_0006:  ldstr      "The Value is: {0}"
  12. IL_000b:  ldloc.0
  13. IL_000c:  ldloc.1
  14. IL_000d:  call int32 ConsoleApplication.MyApp::Add(int32,int32) /* 06000003 */

JIT 编译器读取整个方法的 MSIL,对其进行彻底地分析,然后为该方法生成有效的本机指令。在 IL_000d 遇到Add 方法 (/*06000003 */) 的元数据标记,运行库使用该标记参考 MethodDef 表的第三行。

下表显示了说明 Add 方法的元数据标记所引用的 MethodDef 表的一部分。虽然程序集中存在其他元数据表并具有它们自己唯一的值,但这里只讨论该表。

Row

相对虚拟地址 (RVA)

ImplFlags

Flags

Name

(指向字符串堆。)

Signature(指向 Blob 堆)

1

0x00002050

IL

Managed

Public

ReuseSlot

SpecialName

RTSpecialName

.ctor

.ctor(构造函数)

2

0x00002058

IL

Managed

Public

Static

ReuseSlot

Main

String

3

0x0000208c

IL

Managed

Public

Static

ReuseSlot

Add

int, int, int

该表的每一列都包含有关代码的重要信息。RVA 列允许运行库计算定义该方法的 MSIL 的起始内存地址。ImplFlags 和 Flags 列包含说明该方法的位屏蔽(例如,该方法是公共的还是私有的)。Name 列对来自字符串堆的方法的名称进行了索引。Signature 列对在 Blob 堆中的方法签名的定义进行了索引。

运行库在第三行的 RVA 列计算所需的偏移量地址并将该地址返回到 JIT 编译器,然后,JIT 编译器进入新地址。JIT 编译器继续在新地址处理 MSIL,直到它遇到另一个元数据标记,之后,重复该过程。

使用元数据,运行库可以访问加载代码并将其处理为本机指令所需的所有信息。以这种方式,元数据使自描述文件、公共类型系统和跨语言继承成为可能。

C# 元数据描述的更多相关文章

  1. WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展现[元数据描述篇]

    原文:WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展现[元数据描述篇] 在[WS标准篇]中我花了很大的篇幅介绍了WS-MEX以及与它相关的WS规范:WS-Policy.WS-Tra ...

  2. ASP.NET MVC Model元数据(二)

    ASP.NET MVC Model元数据(二) 前言 在上篇中,给大家留个对Model元数据的印象,并没有对Model元数据有过多的讲解,而在本篇中也不会对Model元数据的本身来解释,而是针对于它的 ...

  3. Java:注解(元数据)

    初识Java注解 所谓的元数据是指用来描述数据的数据,可能刚听到元数据的时候你会有点陌生,其实任何一个使用过struts或者hibernate的开发人员都在不知不觉中使用元数据,更通俗一点来说元数据是 ...

  4. 《BI那点儿事》META DATA(元数据)

    关于数据仓库的数据,指在数据仓库建设过程中所产生的有关数据源定义,目标定义,转换规则等相关的关键数据.同时元数据还包含关于数据含义的商业信息,所有这些信息都应当妥善保存,并很好地管理.为数据仓库的发展 ...

  5. ASP.NET MVC5学习笔记之Action参数模型绑定之模型元数据和元数据提供

    一. 元数据描述类型ModelMetadata 模型元数据是对Model的描述信息,在ASP.NET MVC框架中有非常重要的作用,在模型绑定,模型验证,模型呈现等许多地方都有它的身影.描述Model ...

  6. WCF分布式开发步步为赢(3)WCF服务元数据交换、配置及编程开发

    今天我们继续WCF分布式开发步步为赢(3)WCF服务元数据交换.配置及编程开发的学习.经过前面两节的学习,我们了解WCF分布式开发的相关的基本的概念和自定义宿主托管服务的完整的开发和配置过程.今天我们 ...

  7. 使用Jena RDF API 开发脚本语言管理资源描述框架模型

    摘要 资源描述框架(Resource Description Framework RDF)是一种以XML格式描述元数据的标准格式.Jena是一种用于将关系数据库或是文本文件中所表示的数据建立为元数据模 ...

  8. 如何获取SQL Server数据库元数据的方法

    发布时间:2007.06.15 05:05    来源:赛迪网    作者:3946469 元数据简介 元数据 (metadata) 最常见的定义为“有关数据的结构数据”,或者再简单一点就是“关于数据 ...

  9. 认识元数据和IL(中)<第四篇>

    书接上回[第二十四回:认识元数据和IL(上)],我们对PE文件.程序集.托管模块,这些概念与元数据.IL的关系进行了必要的铺垫,同时顺便熟悉了以ILDASM工具进行反编译的基本方法认知,下面是时候来了 ...

随机推荐

  1. python_paramiko

    目录: paramiko模块介绍 paramiko模块安装 paramiko模块使用 一.paramiko模块介绍 paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件 ...

  2. Chrome浏览器用AdBlockPlus拦截百度广告

    一:安装AdBlockPlus插件,这个貌似要FQ安装,不知道可不可以本地安装: 二:在右侧的扩展那里找到ABP扩展,然后设置-高级-我的过滤列表栏-开始创建我的过滤列表: 三:在列表栏里添加 bai ...

  3. UBUNTU14.0.4安装eclipse

    jdk工具下载地址 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 点击这个下载 ...

  4. html 基本用法

    html表单表格基本用法,直接贴代码. <html> <head> <title>html基础</title> </head> </b ...

  5. PMP:2.项目运行环境

    事业环境因素(EEF):事业环境因素源于项目外部(往往是企业外部)的环境,是指项目团队不能控制的,将对项目产生影响.限制或指令作用的各种条件. 组织内部的事业环境因素: {     uu组织文化.结构 ...

  6. Microsoft在8月7号发布的帮助文档更新中,HelpLibrary2安装Cab文档包出现签名问题

    在VS 2017 8月2号发布15.7.6版本后,在8月7号推送了helpview程序中的绝大部分更新文档,在本次推送中多数Cab文件出现了无法进行安装的签名问题, 不论是单个下载,还是删除本地所有已 ...

  7. javascript事件循环

    js单线程 js是单线程的,这样更有利与用户交互以及DOM操作;有关进程与线程的详细解释可以点击传送门:尽管webworker可以实现多线程,但本质上他还属于单线程,由webworker创建的线程都由 ...

  8. MongoDB 数据库

    数据库: 关系型数据库       mysql           收费        速度快     字段类型 非关系型数据库   MongoDB    不收费    速度慢一些 存储数据都是字符串 ...

  9. ubuntu 16.04 搭建git小型服务器

    最近搭建了一个小型git服务器,由于网上资料鱼龙混杂,让我着实踩了不少地雷.做一个记录,以备不时之需. 一 搞清楚你的需求? 假如你要搭建的服务器只供几十个人使用,并且没有专门的网管服务的话,切记,一 ...

  10. [Leetcode]双项队列解决滑动窗口最大值难题

    这道题是从优先队列的难题里面找到的一个题目.可是解法并不是优先队列,而是双项队列deque 其实只要知道思路,这一道题直接写没有太大的问题.我们看看题 给定一个数组 nums,有一个大小为 k 的滑动 ...