为了更好的理解元数据及其它在CLR中所扮演的角色,自己动手编写代码并且演示元数据是怎么影响CLR是最好的方法。接下来有一个例子,在MyApp中定义了2个方法,Main函数是程序的入口点,Add方法接收两个int数,返回这两个整形数的和。
编译之后生成受控模块。执行该程序时,运行时加载受控模块(关于在.net中运行时如何加载受控模块参考之前的博客
http://blog.csdn.net/lastBeachhead/archive/2008/10/27/3161564.aspx)到内存中,并且向元数据咨询该类的详细信息。当必要时,运行时使用即时编译器把IL语言转换成本地可执行的机器语言。
接下来的是上面Main函数的IL代码。你可以使用ILDasm.exe去查看任何.NET应用程序的MSIL语言和元数据,不过个人推荐使用Reflector.exe。
即时编译器从整个方法中读取MSIL代码,分析代码,然后生成相应的本地指令。在IL_000D,即时编译器发现了一个Add方法的标记,即时编译器使用Add这个标记去向元数据中方法定义表MethodDef中找寻,结果在该表的第三行找到了。
接下来的表格显式了MethodDef表的一部分。受控代码生成的受控模块中还有其它各种各样的表,此处只讨论MethodDef表。
该表的每一列都包含重要的信息。运行时通过RVA列的值去计算出绝对位置。ImpIFlags和Flags两个列包含一些位标记来描述方法。Name列允许运行时根据该列中的名字去从string heap中索引。Signature列允许运行时从blob heap中索引方法签名。
使用元数据,运行时能够访问到所有它需要的信息(去何处装载你的代码以及如何去处理等)。在这种意义上,元数据是一种自描述文件。
- using System;
- public class MyApp
- {
- public static int Main()
- {
- int ValueOne = 10;
- int ValueTwo = 20;
- Console.WriteLine("The Value is: {0}", Add(ValueOne, ValueTwo));
- return 0;
- }
- public static int Add(int One, int Two)
- {
- return (One + Two);
- }
- }
接下来的是上面Main函数的IL代码。你可以使用ILDasm.exe去查看任何.NET应用程序的MSIL语言和元数据,不过个人推荐使用Reflector.exe。
- .entrypoint
- .maxstack 3
- .locals ([0] int32 ValueOne,
- [1] int32 ValueTwo,
- [2] int32 V_2,
- [3] int32 V_3)
- IL_0000: ldc.i4.s 10
- IL_0002: stloc.0
- IL_0003: ldc.i4.s 20
- IL_0005: stloc.1
- IL_0006: ldstr "The Value is: {0}"
- IL_000b: ldloc.0
- IL_000c: ldloc.1
- IL_000d: call int32 ConsoleApplication.MyApp::Add(int32,int32) /* 06000003 */
即时编译器从整个方法中读取MSIL代码,分析代码,然后生成相应的本地指令。在IL_000D,即时编译器发现了一个Add方法的标记,即时编译器使用Add这个标记去向元数据中方法定义表MethodDef中找寻,结果在该表的第三行找到了。
接下来的表格显式了MethodDef表的一部分。受控代码生成的受控模块中还有其它各种各样的表,此处只讨论MethodDef表。
该表的每一列都包含重要的信息。运行时通过RVA列的值去计算出绝对位置。ImpIFlags和Flags两个列包含一些位标记来描述方法。Name列允许运行时根据该列中的名字去从string heap中索引。Signature列允许运行时从blob heap中索引方法签名。
使用元数据,运行时能够访问到所有它需要的信息(去何处装载你的代码以及如何去处理等)。在这种意义上,元数据是一种自描述文件。