解释 .NET 框架中的反射是如何工作的


一个 C# 程序编译成一个 DLL 程序集,其中包含已编译的 C# 代码以及运行时的元数据和其他资源。C# 提供了一个反射 API,允许我们在运行时检查元数据和已编译的代码。

使用反射,可以:

  • 访问程序集元数据以获取程序集内所有类型的信息

  • 获取类型及其成员(方法、属性等)的列表

  • 在运行时动态调用类型成员。

  • 仅提供类型名称即可实例化对象

  • 构建程序集

在传统的程序中,当您将源代码编译成机器码时,编译器会删除有关代码的所有元数据。但是,由于 C# 是一种在公共语言运行时 (CLR) 中运行的托管语言,因此编译器会保留有关代码的大部分信息。反射允许我们检查程序集中的元数据。

System.Reflection 命名空间包含反射所需的所有类和其他类型。您还可以通过 System.Reflection.Emit 命名空间中的类型创建新的元数据并发出中间语言 (IL) 中的可执行代码。

System.Type 使您可以访问类型的元数据。此对象还包含用于枚举类型实例成员的方法,您可以调用这些方法。

using System;
using System.Text;
using System.Reflection;

var sb = new StringBuilder();

// Type at runtime
Type t1 = sb.GetType();
Console.WriteLine(t1.FullName); // System.Text.StringBuilder

// Type at compile-time
Type t2 = typeof (StringBuilder);
Console.WriteLine(t2.FullName); // System.Text.StringBuilder

还可以根据对程序集的引用按名称获取类型。以下示例使用当前程序集并获取在 Models 命名空间中定义的 Person 类的类型。

Type personType = Assembly.GetExecutingAssembly().GetType("CSharp.Models.Person");
Console.WriteLine(personType.FullName); // CSharp.Models.Person

Type 类有一些有用的属性,您可以使用这些属性访问类型的名称、程序集、可见性、基类型等。

using System;
using System.Text;
using System.Reflection;
var sb = new StringBuilder();
// Type at runtime
Type t1 = sb.GetType();
// What's the type's name?
Console.WriteLine(t1.FullName); // System.Text.StringBuilder
// What's the type's base type?
Console.WriteLine(t1.BaseType); // System.Object
// Which assembly is the type defined in?
Console.WriteLine(t1.Assembly); // System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
// Is the type public?
Console.WriteLine(t1.IsPublic); // True

除了这些属性之外,还有 GetProperties()、GetMethods() 和 GetFields() 等方法可以访问类型的成员。重要的是获取对类型 Type 对象的引用。有两种方法可以实现此目的:

object.GetType()

所有类型都包含此函数。它在运行时返回类型

typeof(class)

此表达式在编译时获取类型。它在编译时绑定到特定的 Type 实例,并且直接将类型作为参数。

System.Reflection 命名空间中的类以及 System.Type 命名空间中定义的类允许您获取有关程序集及其内部类型(例如类、接口和值类型)的信息。

更新于: 2021年5月19日

310 次浏览

启动您的 职业生涯

通过完成课程获得认证

开始学习
广告

© . All rights reserved.