.NET 中的反射

命名空间中的System.Reflection类以及System.Type可用于获取有关加载的程序集及其中定义的类型的信息,例如接口和值类型(即结构和枚举)。 还可以使用反射在运行时创建类型实例,以及调用和访问它们。

程序集 包含模块、模块包含类型和类型包含成员。 反射提供封装程序集、模块和类型的对象。 可以使用反射动态创建类型的实例、将类型绑定到现有对象或从现有对象获取类型。 然后,可以调用该类型的方法或访问其字段和属性。 反射的典型用法包括:

  • 用于 Assembly 定义和加载程序集、加载程序集清单中列出的模块,并从此程序集中找到类型并创建它的实例。
  • 使用 Module 可发现包含模块的程序集以及模块中的类等信息。 还可以获取模块上定义的所有全局方法或其他特定非全局方法。
  • ConstructorInfo 发现构造函数的相关信息,例如名称、参数、访问修饰符(如 publicprivate)以及实现详细信息(如 abstractvirtual)等。 使用 GetConstructorsGetConstructorType 方法来调用特定构造函数。
  • 用于 MethodInfo 发现方法的名称、返回类型、参数、访问修饰符和实现详细信息(如 abstractvirtual)等信息。 使用GetMethods中的GetMethodType方法调用特定方法。
  • 使用 FieldInfo 以发现字段的名称、访问修饰符和static等实现详细信息,以及获取或设置字段值。
  • 使用 EventInfo 来发现事件的名称、事件处理程序的数据类型、自定义属性、声明类型和反射的类型等信息,以及添加或删除事件处理程序。
  • 用于 PropertyInfo 发现诸如名称、数据类型、声明类型、反射类型以及属性的只读或可写状态等信息,以及获取或设置属性值。
  • 用于 ParameterInfo 发现参数的名称、数据类型、参数是输入参数还是输出参数以及参数在方法签名中的位置等信息。
  • 当你在 CustomAttributeData 或仅反射上下文 (.NET Framework) 中工作时使用 MetadataLoadContext 发现有关自定义特性的信息。 CustomAttributeData 允许你检查属性,而无需创建它们的实例。

命名空间的 System.Reflection.Emit 类提供了一种专用的反射形式,可用于在运行时生成类型。

反射还可用于创建 类型浏览器,使用户能够选择类型,然后查看有关这些类型的信息。

反射还有其他用途。 JScript 等语言的编译器使用反射来构造符号表。 命名空间中的 System.Runtime.Serialization 类使用反射来访问数据并确定要保留的字段。 命名空间中的 System.Runtime.Remoting 类通过序列化间接使用反射。

反射中的运行时类型

反射提供类(如 TypeMethodInfo)来表示类型、成员、参数和其他代码实体。 但是,使用反射时,不能直接使用这些类,其中大多数是抽象类(MustInherit 在 Visual Basic 中)。 相反,你使用由公共语言运行时 (CLR) 提供的类型。

例如,使用 C# typeof 运算符(GetType 在 Visual Basic 中)获取 Type 对象时,该对象实际上是一个 RuntimeTypeRuntimeType 派生自 Type 并提供所有抽象方法的实现。

这些运行时类是 internal(在 Visual Basic 中为 Friend)。 它们不会与其基类分开记录,因为它们的行为由基类文档描述。

参考文献