关于C#反射 你需要知道的

2020-06-09 19:00:23王冬梅

通常,反射用于动态获取对象的类型、属性和方法等信息。今天带你玩转反射,来汇总一下反射的各种常见操作,捡漏看看有没有你不知道的。

获取类型的成员

Type 类的 GetMembers 方法用来获取该类型的所有成员,包括方法和属性,可通过 BindingFlags 标志来筛选这些成员。

using System;
using System.Reflection;
using System.Linq;

public class Program
{
  public static voidMain()
  {
    var members = typeof(object).GetMembers(BindingFlags.Public |
      BindingFlags.Static | BindingFlags.Instance);
    foreach (var member in members)
    {
      Console.WriteLine($"{member.Name} is a {member.MemberType}");
    }
  }
}

输出:

GetType is a Method
GetHashCode is a Method
ToString is a Method
Equals is a Method
ReferenceEquals is a Method
.ctor is a Constructor

GetMembers 方法也可以不传 BindingFlags,默认返回的是所有公开的成员。

获取并调用对象的方法

Type 类型的 GetMethod 方法用来获取该类型的 MethodInfo,然后可通过 MethodInfo 动态调用该方法。

对于非静态方法,需要传递对应的实例作为参数,示例:

class Program
{
  public static void Main()
  {
    var str = "hello";
    var method = str.GetType()
      .GetMethod("Substring", new[] {typeof(int), typeof(int)});
    var result = method.Invoke(str, new object[] {0, 4}); // 相当于 str.Substring(0, 4)
    Console.WriteLine(result); // 输出:hell
  }
}

对于静态方法,则对象参数传空,示例:

var method = typeof(Math).GetMethod("Exp");
// 相当于 Math.Exp(2)
var result = method.Invoke(null, new object[] {2});
Console.WriteLine(result); // 输出(e^2):7.38905609893065

如果是泛型方法,则还需要通过泛型参数来创建泛型方法,示例:

class Program
{
  public static void Main()
  {
    // 反射调用泛型方法
    MethodInfo method1 = typeof(Sample).GetMethod("GenericMethod");
    MethodInfo generic1 = method1.MakeGenericMethod(typeof(string));
    generic1.Invoke(sample, null);

    // 反射调用静态泛型方法
    MethodInfo method2 = typeof(Sample).GetMethod("StaticMethod");
    MethodInfo generic2 = method2.MakeGenericMethod(typeof(string));
    generic2.Invoke(null, null);
  }
}

public class Sample
{
  public void GenericMethod<T>()
  {
    //...
  }
  public static void StaticMethod<T>()
  {
    //...
  }
}

创建一个类型的实例

使用反射动态创建一个类型的实例有多种种方式。最简单的一种是用 new() 条件声明。

使用 new 条件声明

如果在一个方法内需要动态创建一个实例,可以直接使用 new 条件声明,例如:

T GetInstance<T>() where T : new()
{
  T instance = newT();
  return instance;
}