解释反射如何在 .NET 框架中工作
AC#程序编译为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 t1 = sb.GetType(); Console.WriteLine(t1.FullName); //System.Text.StringBuilder //编译时输入 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 t1 = sb.GetType(); //What'sthetype'sname? Console.WriteLine(t1.FullName); //System.Text.StringBuilder //What'sthetype'sbasetype? Console.WriteLine(t1.BaseType); //System.Object //Whichassemblyisthetypedefinedin? Console.WriteLine(t1.Assembly); //System.Private.CoreLib,Version=5.0.0.0,Culture=neutral,PublicKeyToken=7cec85d7bea7798e //Isthetypepublic? Console.WriteLine(t1.IsPublic); // True
随着这些特性,还有诸如方法GetProperties(),GetMethods()以及GetFields()提供访问类型的成员。重要的是获得对类型的Type对象的引用。有两种方法可以实现这一点-
object.GetType():
所有类型都包含此功能。它在运行时返回类型
类型(类):
此表达式在编译时获取类型。它在编译时绑定到特定的Type实例,并直接将类型作为参数。
System.Reflection命名空间中的类以及命名空间中定义的类System.Type允许您获取有关程序集及其中类型的信息,例如类、接口和值类型。