更新:2007 年 11 月
反射允许在运行时检查已知数据类型。例如,反射允许使用给定程序集中的数据类型的枚举,并且可以发现给定类或值类型中的成员。无论类型是否已知或者在编译时被引用,都是如此。这使反射成为开发和代码管理工具的一项有用功能。
请注意,所提供的程序集名称是强名称(请参见具有强名称的程序集),其中包括程序集版本、区域性和签名信息。另请注意,可以检索在其中定义数据类型的命名空间的名称以及基类的名称。
若要访问反射功能,最常见的方式是通过 GetType 方法。此方法由 System::Object 提供,所有垃圾回收类都从其派生。
如果 .exe 是用 /clr:pure 或 /clr:safe 编译器选项生成的,允许使用用 Visual C++ 编译器生成的 .exe 上的反射。有关更多信息,请参见 /clr(公共语言运行库编译)。
此节中的主题:
有关更多信息,请参见
GetType 方法返回指向 Type 类对象的指针,该类对象描述对象所基于的类型。(“Type”对象不包含任何实例特定信息。) 类型的全名就是这样的对象,它可能显示如下:
请注意,类型名称包括整个类型定义范围(包括命名空间),并且以 .NET 语法显示(以点号作为范围解析运算符)。
值类型也可以与 GetType 函数一起使用,但它们必须首先装箱。
与 GetType 方法一样,typeid 运算符将返回一个指向“Type”对象的指针,所以此代码指示类型名 System.Int32。反射的最基本功能是显示类型名,但是可能更有用的技术是检查或发现枚举类型的有效值。这可以通过使用静态 Enum::GetNames 函数来实现,该函数返回一个字符串数组,每个字符串包含文本形式的枚举值。 下面的示例检索一个字符串数组,它描述“Options”(CLR) 枚举的值枚举值并在一个循环中显示这些值。
如果向“Options”枚举添加第四个选项,此代码将在不重新编译的情况下报告新的选项(即使该枚举是在单独的程序集中定义的)。
GetType 对象支持大量可用来检查类型的成员和属性。此代码检索并显示此信息中的一部分:
反射还允许枚举程序集内的类型和类中的成员。为了说明此功能,请定义一个简单类:
如果已将上面的代码编译到称为 vcpp_reflection_6.dll 的 DLL 中,则您可以使用反射检查此程序集的内容。这包括使用静态反射 API 函数 Assembly::Load 来加载程序集。此函数返回 Assembly 对象的地址,然后它可以在该对象中查询关于模块和类型的信息。
反射系统一旦成功加载程序集,即会用 Assembly::GetTypes 函数检索“Type”对象的数组。每个数组元素都包含关于不同类型的信息(虽然本例中只定义了一个类)。通过循环,将使用 Type::GetMembers 函数对此数组中的每个“Type”查询关于类型成员的信息。此函数返回一个 MethodInfo 对象的数组,每个对象都包含关于类型中成员函数、数据成员或属性的信息。
请注意,方法列表包含在 TestClass 中显式定义的函数以及从 System::Object 类隐式继承的函数。在用 .NET(而不是用 Visual C++ 语法)进行描述时,属性将显示为由 get/set 函数访问的基础数据成员。get/set 函数在此列表中显示为规则方法。整个公共语言运行库都支持反射,但 Visual C++ 编译器不支持反射。
虽然您使用此代码来检查已定义的程序集,但也可以使用此代码来检查 .NET 程序集。例如,如果将 TestAssembly 更改为 mscorlib,则将看到在 mscorlib.dll 中定义的每个类型和方法的列表。