Skip to content

C# 通过反射执行泛型类的方法

🏷️ C# 泛型

有个需求需要实现根据参数中指定类型,反序列化一个 JSON 字符串,然后将反序列化后的结果传到一个泛型类的方法。

示例用类:

csharp
namespace N {
    class A {

    }

    class B<T> {
        public M(T t) {

        }
    }
}

需要实现的方法:

csharp
void V (string typeName, string jsonData) {

}

如果采用如下方法调用(GetType 方法见文章后面的 附 1

csharp
void V (string typeName, string jsonData) {
    var typeA = GetType(typeName);
    var b = new B<typeA>();
}

则会报错:

“typeA”是 变量,但此处被当做 类型 来使用

应使用 MakeGenericType 方法来创建泛型类的类型,之后再通过 Activator.CreateInstance 方法创建实例(参考 这篇博客),示例如下:

csharp
void V (string typeName, string jsonData) {
    // 反序列化 json 为指定类型
    var typeA = GetType(typeName);
    var data = JsonConvert.DeserializeObject(jsonData, typeA);
    // 创建泛型类的类型
    var typeB = typeof(B<>).MakeGenericType(typeA);
    // 创建泛型类的实例
    object objB = Activator.CreateInstance(typeB);
    // 获取泛型类的方法并调用
    MethodInfo method = typeB.GetMethod("M", BindingFlags.Instance | BindingFlags.Public);
    method.Invoke(objB, new object[] { data });
}

附 1. GetType

方法如下(参考自 这篇博客):

csharp
/// <summary>
/// 根据字符串获取 Type
/// </summary>
/// <param name="typeName"></param>
/// <returns></returns>
private Type GetType(string typeName)
{
    Type type = null;
    Assembly[] assemblyArray = AppDomain.CurrentDomain.GetAssemblies();
    int assemblyArrayLength = assemblyArray.Length;
    for (int i = 0; i < assemblyArrayLength; ++i)
    {
        type = assemblyArray[i].GetType(typeName);
        if (type != null)
        {
            return type;
        }
    }
    return type;
}