Skip to content

.NET Core 实战 [No.306~312] 反射

🏷️ 《.NET Core 实战》

反射技术可以在应用程序运行阶段对程序进行解析,包括获取程序集中的类型、类型的成员列表、参数列表等信息,还可以创建类型实例或调用类型成员。

与反射有关的类型都位于 System.Reflection 命名空间下。

1. Assembly

提供了一系列加载程序的静态方法,最常用的是 LoadFrom 静态方法,通过 dll 文件加载程序集,返回值是一个 Assembly 实例。

csharp
Assembly ass = Assembly.LoadFrom("TestLib.dll");

通过 Assembly 实例的属性可以获取程序集的一些基本信息,通过 GetTypes 方法可以获取该程序集的类型列表,GetType 方法可以获取指定的类型。

csharp
Type[] types = ass.GetTypes();
Type testType = ass.GetType("Test");

2. Type

Type 类型也提供一些静态方法用以获取类型,如 GetType 方法。

获取到类型实例之后,可以通过如下方法获取类型的成员:

  • GetMethodsGetMethod:获取方法(MethodInfo)。
  • GetPropertiesGetProperty:获取属性(PropertyInfo)。
  • GetEventsGetEvent:获取事件(EventInfo)。
  • GetConstructorsGetConstructor:获取构造函数(ConstructorInfo)。
  • GetFieldsGetField:获取字段(FieldInfo)。
  • GetMembersGetMember:获取以上所有类型的成员(MemberInfo)。

上述方法默认仅获取公共成员,若要获取非公有成员,可以通过调用带 BindingFlags 枚举参数的对应方法。比如若要获取静态方法,可以将参数 bindingAttr 设置为 BindingFlags.Static

3. MethodInfo

MethodInfo 类封装了常规方法(不包括构造函数)的相关信息。从上一节可以知道通过 GetMethodsGetMethod 方法可以获取到 MethodInfo 实例。

常用方法如下:

  • GetParameters:获取方法的参数列表信息。

  • InvokeInvoke 位于 MethodInfo 的基类 MethodBase 类中,用于执行当前方法。

    Invoke 有两个重载,常用的是下面这个:obj 为运行当前方法的实例,parameters 为方法的参数。

    csharp
    public object Invoke(object obj, object[] parameters);

    调用静态方法时,由于没有对应的实例,obj 应传空值 null

4. ConstructorInfo

ConstructorInfo 类封装了构造函数的相关信息,同 MethodInfo 一样也继承自 MethodBase

通过 Type 类的 GetConstructorsGetConstructor 可以获取到构造函数的实例。需要注意的是由于 GetConstructor 没有无参的重载,所以获取无参的构造函数时需要传 Type.EmptyTypes 进去。

csharp
ConstructorInfo constr = testType.GetConstructor(Type.EmptyTypes);

调用构造函数方法时也是通过 Invoke 方法。

csharp
public object Invoke(object[] parameters);

调用无参构造函数时参数为 null

csharp
object instance = constr.Invoke(null);

5. Activator

Activator 类仅有一个静态方法 CreateInstance,用于创建类型的实例,但该方法有多个重载,常用的是如下两个版本。

调用类型的无参构造函数创建实例:

csharp
public static object CreateInstance(Type type);

调用类型的带参数的构造函数创建实例:

csharp
public static object CreateInstance(Type type, params object[] args);

下面是调用无参构造函数的示例:

csharp
object instance = Activator.CreateInstance(testType);

6. CustomAttribute

CustomAttributeExtensions 类对如下类型提供了 GetCustomAttributeGetCustomAttributesIsDefined 扩展方法。

  • ParameterInfo
  • Assembly
  • MemberInfo
  • Module
  • ParameterInfo

在上面几节提到的几种成员类型(MethodInfoPropertyInfoEventInfoConstructorInfoFieldInfo)都是 MemberInfo 的派生类。

上面三个扩展方法中 GetCustomAttributeGetCustomAttributes 方法用于获取成员上应用的特性(Attribute)。示例如下:

csharp
DataContractAttribute dataContractAttribute = testType.GetCustomAttribute<DataContractAttribute>();
Console.WriteLine($"类型 {testType.Name} 的数据协定名是:{dataContractAttribute.Name}");

参考:《.NET Core 实战:手把手教你掌握 380 个精彩案例》 -- 周家安 著