在 C# 中,反射允许我们在运行时检查和操作类、构造函数、方法和字段。
例如,我们定义了一个名为 Student 的类,如下所示:
class Student
{
// a field
public int age;
// method
public void score()
{
// .. some code
}
}
上面的 Student 类包含一个字段和一个方法。借助反射,我们可以在运行时检查这些信息。
我们将在下面详细介绍反射。
什么是 C# 反射?
在 C# 中,有一个称为 **程序集 (Assembly)** 的块,它由编译器在代码成功编译后自动生成。它包含两个部分:中间语言和元数据。
当我们编写 C# 代码时,它不会直接编译成机器级语言。它首先被编译成一种中间语言,然后打包成 **程序集**。
类似地,元数据包含有关类型(如类、方法、构造函数等)的信息。例如,一个 Student 类包含一些方法和字段。所有这些关于 Student 类的信息都以元数据的形式存在。
反射就是简单地获取这些元数据并检查其中的信息。
C# 反射层次结构
C# 提供了 System.Reflection 命名空间,我们可以使用它来执行反射。System.Reflection 命名空间包含以下类:
上图显示了 System.Reflection 命名空间下的一些类。在这些类中,我们将使用 Type 类来演示反射。
C# Type 类
访问元数据的主要方法是使用 Type 类。此类提供了方法和属性,我们可以使用它们来获取有关类型声明的信息。例如:
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
String studentName = "Jack";
// get the current type of studentName
Type studentNameType = studentName.GetType();
Console.WriteLine("Type is: " + studentNameType);
}
}
输出
Type is: System.String
在上面的示例中,我们定义了一个 String 类变量 studentName。请注意代码:
// get the current type of studentName
Type studentNameType = studentName.GetType();
GetType() 方法返回当前数据的 Type。在这里,我们使用了带有 studentName 的 GetType() 并将其赋值给 Type 变量 studentNameType。
GetType() 方法返回 System.String,这是 studentName 的当前类型。
示例 1:C# 反射获取程序集
Type 类提供了一个名为 Assembly 的属性,该属性会生成代码的程序集。例如:
using System;
using System.Reflection;
class Program
{
static void Main()
{
// get typeof the Program class and load it to Type variable t
Type t = typeof(Program);
// get Assembly of variable t using the Assembly property
Console.WriteLine(t.Assembly);
}
}
输出
app, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
在上面的示例中,请注意代码,
// get type of Program and load it to Type variable t
Type t = typeof(Program);
在这里,我们使用了 typeof 运算符,它返回 Program 类的类型,并将其赋值给 Type 变量 t。
然后,我们使用 t 的 Assembly 属性,即 t.Assembly,它返回 Program 类的程序集。
示例 2:C# 反射与 Enumerable
我们可以使用 Type 类的属性来获取有关 Enumerable 类型的信息。例如:
using System;
using System.Reflection;
class Program
{
static void Main()
{
// get typeof Enumerable and load it to Type variable t
Type t = typeof(Enumerable);
// the Type class properties return information about the Enumerable Type
Console.WriteLine("Name : {0}", t.Name);
Console.WriteLine("Namespace : {0}", t.Namespace);
Console.WriteLine("Base Type : {0}", t.BaseType);
}
}
输出
Name : Enumerable Namespace : System.Linq Base Type : System.Object
在上面的示例中,我们使用了 Type 类的属性以及 Enumerable 类型:
t.Name- 获取类型的名称t.Namespace- 获取类型的命名空间t.BaseType- 获取基类型或父类型
示例 3:C# 反射与 String
我们也可以使用 Type 类的属性来获取有关 String 类型的信息。例如:
using System;
using System.Reflection;
class Program
{
static void Main()
{
// get typeof String and load it to Type variable t
Type t = typeof(String);
// the Type class properties return information about the String Type
Console.WriteLine("Name : {0}", t.Name);
Console.WriteLine("Namespace : {0}", t.Namespace);
Console.WriteLine("Base Type : {0}", t.BaseType);
}
}
输出
Name : String Namespace : System Base Type : System.Object
注意: 我们可以使用 C# 中的反射获取有关其他类型(如 *class*、*delegate*、*array* 等)的信息。