众所周知,元数据时是用一系列表来存储的。生成一个程序集或模块时,编译器会创建一个类型定义表,一个字段定义表,一个方法定义表以及其他表。利用System.Reflection命名空间中包含的一些类型,可以写代码来反射这些元数据。实际上,这个命名空间中的类型为程序集或模块中包含的元数据创建了一个对象模型。
利用这个对象模型中的类型,可轻松枚举一个类型定义元数据表中的所有类型。然后,针对每个类型,都可以获取它的基类型,它实现的一些接口以及与类型关联的一些标志。利用System.Reflection命名空间中的其他类型,还可解析对应的元数据表来查询类型的字段,方法,属性和事件,还可发现应用于任何元数据实体的任何定制attribute。甚至有一些类型允许判断引用的程序集;还有一些方法,他们返回一个方法的IL字节流。利用所有这些信息,很容易构建一个和ILDASM.EXE非常相似的工具。
事实上,只要极少数应用程序才需要使用反射类型。反射一般由某些类库使用,他们需要理解类型的定义才能提供丰富的功能。例如,FCL的序列化机制就是利用反射来判断一个类型定义了哪些字段。然后,序列化格式器可以获取这些字段的值,并把他们写入一个字节流,以便通过Internet传送,保存到文件或者复制到剪切板。类似的,在设计期间,Microsoft Visual Studio 设计器在Web窗体或Window窗体上放置控件时,也利用反射来决定向开发人员显示的属性。
在运行时,应用程序需要从一个特定的程序集中加载一个特定的类型,以执行特定的任务时,也要使用反射。例如,应用程序可要求用户提供一个程序集和一个类型的名称。然后,应用程序可以显示加载程序集,构造一个类型的实例,再调用类型中定义的方法。这种用法在概念上类似于调用Win 32 LoadLibrary和GetProcAddress函数,这种方式绑定到类型并调用方法通常称为晚期绑定。