反射(Reflection)是 C# 的 "元编程" 能力,允许程序在运行时 获取类型信息、调用方法、创建实例;泛型(Generic)则是 "类型参数化",实现类型安全的代码复用。两者结合可突破静态泛型的限制,实现动态绑定泛型参数、调用泛型方法、操作泛型成员,是框架开发(如 DI 容器、ORM、序列化)的核心技术。
本文将从 "基础概念→核心 API→分场景超详细案例→底层原理→避坑指南" 全维度讲解,所有案例均为可直接运行的控制台程序,每一行代码都附带注释和原理说明。
一、核心概念前置
在开始案例前,先明确反射操作泛型的核心术语,避免概念混淆:
|----------------------|-------------------------------------------|------------------------------------------------|
| 术语 | | 定义 | |----| | | 示例 | |----| |
| 泛型定义(未绑定类型) | 未指定具体泛型参数的泛型类型 / 方法,仅表示 "模板",无法直接实例化 / 调用 | typeof(GenericClass<>)、MethodInfo(泛型方法定义) |
| 已绑定类型 / 方法 | 绑定了具体泛型参数的泛型类型 / 方法,可实例化 / 调用 | typeof(GenericClass<int>)、绑定了<string>的泛型方法 |
| 泛型参数(Type Argument) | 绑定到泛型定义的具体类型(如 int、string) | MakeGenericType(typeof(int)) 中的 int |
| 泛型形参(Type Parameter) | 泛型定义中的占位符(如<T>、<U>) | class GenericClass<T> 中的 T |
二、核心 API 全解析(反射操作泛型的 "工具箱")
以下是反射操作泛型的核心 API,按 "类型操作→方法操作→成员操作" 分类,每个 API 附带用途和使用场景:
2.1 泛型类型操作 API
|---------------------------------------|-----------------------------------------------------|
| API | | 用途 | |----| |
| Type.IsGenericType | 判断类型是否是已绑定的泛型类型 (如GenericClass<int>返回 true) |
| Type.IsGenericTypeDefinition | 判断类型是否是泛型定义 (如GenericClass<>返回 true) |
| Type.GetGenericTypeDefinition() | 从已绑定类型获取泛型定义(如GenericClass<int>→GenericClass<>) |
| Type.MakeGenericType(params Type[]) | 绑定泛型参数,从泛型定义生成已绑定类型(核心 API) |
| Type.GetGenericArguments() | 获取泛型参数数组(已绑定类型返回具体类型,泛型定义返回形参) |
2.2 泛型方法操作 API
|-----------------------------------------------|--------------------------------|
| API | 用途 |
| MethodInfo.IsGenericMethod | 判断方法是否是泛型方法(已绑定 / 未绑定均返回 true) |
| MethodInfo.IsGenericMethodDefinition | 判断方法是否是泛型方法定义(未绑定参数) |
| MethodInfo.MakeGenericMethod(params Type[]) | 绑定泛型参数,从泛型方法定义生成已绑定方法(核心 API) |
| MethodInfo.GetGenericArguments() | 获取方法的泛型参数数组 |
2.3 实例 / 成员操作 API
|----------------------------------------------------|----------------------------|
| API | | 用途 | |----| |
| Activator.CreateInstance(Type, params object[]) | 创建泛型类型实例(支持无参 / 带参构造) |
| MethodInfo.Invoke(object, object[]) | 调用泛型方法(实例方法传实例,静态方法传 null) |
| PropertyInfo.GetValue(object)/SetValue(object) | 读写泛型类型的属性 |
三、控制台案例(分 8 个核心场景)
所有案例基于同一控制台项目,先定义测试用的泛型类型(类、接口、方法),再分场景演示反射操作。
3.0 准备测试用泛型类型(基础依赖)
先定义一套覆盖 "泛型类、泛型接口、泛型方法(实例 / 静态 / 重载)、泛型属性 / 字段" 的测试类型,后续所有反射操作均基于此:
cs
using System;
using System.Collections.Generic;
using System.Reflection;
namespace ReflectionGenericUltraDetail
{
#region 测试用泛型类型定义(核心依赖)
/// <summary>
/// 泛型测试类(包含泛型字段、属性、构造函数、实例泛型方法、静态泛型方法、重载泛型方法)
/// </summary>
/// <typeparam name="T">主泛型参数</typeparam>
public class GenericTestClass<T>
{
// 泛型字段
public T GenericField;
// 泛型属性
public T GenericProperty { get; set; }
// 非泛型属性(对比)
public int NonGenericProperty { get; set; } = 0;
#region 构造函数(无参/单参/多参)
/// <summary>
/// 无参构造函数
/// </summary>
public GenericTestClass()
{
Console.WriteLine($"【构造函数】GenericTestClass<{typeof(T).Name}> 无参构造执行");
}
/// <summary>
/// 单参构造函数(泛型参数类型)
/// </summary>
/// <param name="initValue">泛型类型的初始值</param>
public GenericTestClass(T initValue)
{
GenericField = initValue;
GenericProperty = initValue;
Console.WriteLine($"【构造函数】GenericTestClass<{typeof(T).Name}> 单参构造执行,初始值:{initValue}");
}
/// <summary>
/// 多参构造函数(泛型+非泛型参数)
/// </summary>
/// <param name="initValue">泛型初始值</param>
/// <param name="nonGenericValue">非泛型int值</param>
public GenericTestClass(T initValue, int nonGenericValue)
{
GenericField = initValue;
GenericProperty = initValue;
NonGenericProperty = nonGenericValue;
Console.WriteLine($"【构造函数】GenericTestClass<{typeof(T).Name}> 多参构造执行,泛型值:{initValue},非泛型值:{nonGenericValue}");
}
#endregion
#region 实例方法(泛型/非泛型/重载)
/// <summary>
/// 非泛型实例方法
/// </summary>
public void NonGenericInstanceMethod()
{
Console.WriteLine($"【实例方法】非泛型方法执行,泛型类型:{typeof(T).Name},GenericProperty值:{GenericProperty}");
}
/// <summary>
/// 泛型实例方法(单泛型参数)
/// </summary>
/// <typeparam name="U">方法级泛型参数</typeparam>
/// <param name="input1">类泛型参数T类型</param>
/// <param name="input2">方法泛型参数U类型</param>
public void GenericInstanceMethod<U>(T input1, U input2)
{
Console.WriteLine($"【实例方法】泛型方法<{typeof(U).Name}>执行,输入1({typeof(T).Name}):{input1},输入2({typeof(U).Name}):{input2}");
}
/// <summary>
/// 泛型实例方法(重载版)
/// </summary>
/// <typeparam name="U">方法级泛型参数</typeparam>
/// <typeparam name="V">第二个方法级泛型参数</typeparam>
/// <param name="input1">T类型</param>
/// <param name="input2">U类型</param>
/// <param name="input3">V类型</param>
public void GenericInstanceMethod<U, V>(T input1, U input2, V input3)
{
Console.WriteLine($"【实例方法】泛型方法<{typeof(U).Name},{typeof(V).Name}>重载版执行,输入1:{input1},输入2:{input2},输入3:{input3}");
}
#endregion
#region 静态方法(泛型/非泛型)
/// <summary>
/// 非泛型静态方法
/// </summary>
/// <param name="message">字符串参数</param>
public static void NonGenericStaticMethod(string message)
{
Console.WriteLine($"【静态方法】非泛型静态方法执行,消息:{message}");
}
/// <summary>
/// 泛型静态方法
/// </summary>
/// <typeparam name="W">静态方法泛型参数</typeparam>
/// <param name="value">W类型参数</param>
public static void GenericStaticMethod<W>(W value)
{
Console.WriteLine($"【静态方法】泛型静态方法<{typeof(W).Name}>执行,值:{value}");
}
#endregion
}
/// <summary>
/// 泛型接口(测试泛型接口反射)
/// </summary>
/// <typeparam name="T">接口泛型参数</typeparam>
public interface IGenericTestInterface<T>
{
T GetData();
void SetData(T data);
void GenericInterfaceMethod<U>(T input, U output);
}
/// <summary>
/// 泛型接口实现类
/// </summary>
/// <typeparam name="T">实现类泛型参数</typeparam>
public class GenericInterfaceImplement<T> : IGenericTestInterface<T>
{
private T _data;
public T GetData()
{
Console.WriteLine($"【接口实现】GetData()执行,返回值:{_data}");
return _data;
}
public void SetData(T data)
{
_data = data;
Console.WriteLine($"【接口实现】SetData()执行,设置值:{data}");
}
public void GenericInterfaceMethod<U>(T input, U output)
{
Console.WriteLine($"【接口实现】泛型接口方法<{typeof(U).Name}>执行,输入:{input},输出:{output}");
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("==================================== 场景1:泛型类型的反射基础操作 ====================================");
Scene1_GenericTypeBasicOperations();
Console.WriteLine("\n==================================== 场景2:动态创建泛型类实例(全构造函数) ====================================");
Scene2_CreateGenericInstance();
Console.WriteLine("\n==================================== 场景3:动态调用泛型实例方法(含重载) ====================================");
Scene3_CallGenericInstanceMethod();
Console.WriteLine("\n==================================== 场景4:动态调用泛型静态方法 ====================================");
Scene4_CallGenericStaticMethod();
Console.WriteLine("\n==================================== 场景5:反射操作泛型字段/属性 ====================================");
Scene5_ReflectGenericFieldProperty();
Console.WriteLine("\n==================================== 场景6:泛型接口的反射操作 ====================================");
Scene6_ReflectGenericInterface();
Console.WriteLine("\n==================================== 场景7:嵌套泛型的反射处理 ====================================");
Scene7_HandleNestedGeneric();
Console.WriteLine("\n==================================== 场景8:泛型方法重载的精准获取 ====================================");
Scene8_GetOverloadGenericMethod();
Console.ReadKey();
}
3.1 场景 1:泛型类型的反射基础操作
目标:掌握 "泛型定义" 与 "已绑定类型" 的区分、核心属性判断、泛型参数获取。
cs
/// <summary>
/// 场景1:泛型类型的反射基础操作(泛型定义/已绑定类型区分、参数获取)
/// </summary>
static void Scene1_GenericTypeBasicOperations()
{
// 1. 获取泛型定义(未绑定类型):typeof(类名<>),注意<>内无参数
Type genericDefinition = typeof(GenericTestClass<>);
Console.WriteLine($"1. 泛型定义类型名:{genericDefinition.FullName}");
Console.WriteLine($" - 是否是泛型定义:{genericDefinition.IsGenericTypeDefinition}");
Console.WriteLine($" - 是否是泛型类型:{genericDefinition.IsGenericType}"); // 泛型定义也是泛型类型
Console.WriteLine($" - 泛型形参数量:{genericDefinition.GetGenericArguments().Length}"); // 1个形参(T)
Console.WriteLine($" - 泛型形参名称:{genericDefinition.GetGenericArguments()[0].Name}"); // T
// 2. 绑定泛型参数,生成已绑定类型(核心:MakeGenericType)
Type boundType_Int = genericDefinition.MakeGenericType(typeof(int));
Console.WriteLine($"\n2. 绑定int后的已绑定类型名:{boundType_Int.FullName}");
Console.WriteLine($" - 是否是泛型定义:{boundType_Int.IsGenericTypeDefinition}"); // false(已绑定)
Console.WriteLine($" - 是否是泛型类型:{boundType_Int.IsGenericType}"); // true
Console.WriteLine($" - 泛型实参类型:{boundType_Int.GetGenericArguments()[0].Name}"); // Int32(具体类型)
// 3. 从已绑定类型反推泛型定义(GetGenericTypeDefinition)
Type derivedDefinition = boundType_Int.GetGenericTypeDefinition();
Console.WriteLine($"\n3. 从已绑定类型反推的泛型定义:{derivedDefinition.FullName}");
Console.WriteLine($" - 与原泛型定义是否相同:{derivedDefinition == genericDefinition}"); // true
// 4. 非泛型类型的对比(验证属性)
Type nonGenericType = typeof(string);
Console.WriteLine($"\n4. 非泛型类型(string):");
Console.WriteLine($" - 是否是泛型类型:{nonGenericType.IsGenericType}"); // false
Console.WriteLine($" - 是否是泛型定义:{nonGenericType.IsGenericTypeDefinition}"); // false
}
运行结果:
cs
1. 泛型定义类型名:ReflectionGenericUltraDetail.GenericTestClass`1
- 是否是泛型定义:True
- 是否是泛型类型:True
- 泛型形参数量:1
- 泛型形参名称:T
2. 绑定int后的已绑定类型名:ReflectionGenericUltraDetail.GenericTestClass`1[[System.Int32, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
- 是否是泛型定义:False
- 是否是泛型类型:True
- 泛型实参类型:Int32
3. 从已绑定类型反推的泛型定义:ReflectionGenericUltraDetail.GenericTestClass`1
- 与原泛型定义是否相同:True
4. 非泛型类型(string):
- 是否是泛型类型:False
- 是否是泛型定义:False
核心说明:
- 泛型定义是 "模板",无法直接实例化(
Activator.CreateInstance(typeof(GenericTestClass<>))会报错); - 必须通过
MakeGenericType绑定具体类型,生成 "已绑定类型" 后才能实例化 / 调用方法; GetGenericTypeDefinition()是 "反向操作",可从已绑定类型还原泛型定义,用于缓存泛型模板。
3.2 场景 2:动态创建泛型类实例(全构造函数)
目标:掌握无参、单参、多参构造函数的泛型实例创建,解决 "构造函数参数匹配" 问题。
cs
/// <summary>
/// 场景2:动态创建泛型类实例(无参/单参/多参构造函数)
/// </summary>
static void Scene2_CreateGenericInstance()
{
// 步骤1:获取泛型定义并绑定int类型(已绑定类型)
Type genericDefinition = typeof(GenericTestClass<>);
Type boundType_Int = genericDefinition.MakeGenericType(typeof(int));
// 子场景1:无参构造创建实例
Console.WriteLine("【子场景1】无参构造创建实例");
object instance_NoParam = Activator.CreateInstance(boundType_Int);
Console.WriteLine($" - 实例类型:{instance_NoParam.GetType().FullName}");
Console.WriteLine($" - 转换为强类型:{instance_NoParam is GenericTestClass<int>}"); // true
// 子场景2:单参构造创建实例(参数为泛型类型)
Console.WriteLine("\n【子场景2】单参构造创建实例(int类型参数:99)");
object instance_SingleParam = Activator.CreateInstance(boundType_Int, 99); // 第二个参数是构造函数参数数组
// 验证:获取GenericProperty属性值(后续场景会详解属性反射,此处先强转)
GenericTestClass<int> strongType_SingleParam = instance_SingleParam as GenericTestClass<int>;
Console.WriteLine($" - 实例的GenericProperty值:{strongType_SingleParam.GenericProperty}"); // 99
// 子场景3:多参构造创建实例(泛型参数+非泛型参数)
Console.WriteLine("\n【子场景3】多参构造创建实例(int:88,非泛型int:1000)");
object instance_MultiParam = Activator.CreateInstance(boundType_Int, 88, 1000);
GenericTestClass<int> strongType_MultiParam = instance_MultiParam as GenericTestClass<int>;
Console.WriteLine($" - GenericProperty值:{strongType_MultiParam.GenericProperty}"); // 88
Console.WriteLine($" - NonGenericProperty值:{strongType_MultiParam.NonGenericProperty}"); // 1000
// 扩展:绑定string类型,创建单参实例
Console.WriteLine("\n【扩展】绑定string类型,单参构造(参数:\"Hello Reflection\")");
Type boundType_String = genericDefinition.MakeGenericType(typeof(string));
object instance_String = Activator.CreateInstance(boundType_String, "Hello Reflection");
GenericTestClass<string> strongType_String = instance_String as GenericTestClass<string>;
Console.WriteLine($" - String类型实例的GenericProperty:{strongType_String.GenericProperty}");
// 异常场景演示(构造函数参数类型不匹配)
try
{
Console.WriteLine("\n【异常演示】构造函数参数类型不匹配(int类型实例传string参数)");
Activator.CreateInstance(boundType_Int, "错误的字符串参数");
}
catch (TargetInvocationException ex)
{
Console.WriteLine($" - 异常信息:{ex.InnerException.Message}"); // 无法将string转换为int
}
}
运行结果:
cs
【子场景1】无参构造创建实例
【构造函数】GenericTestClass<Int32> 无参构造执行
- 实例类型:ReflectionGenericUltraDetail.GenericTestClass`1[[System.Int32, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
- 转换为强类型:True
【子场景2】单参构造创建实例(int类型参数:99)
【构造函数】GenericTestClass<Int32> 单参构造执行,初始值:99
- 实例的GenericProperty值:99
【子场景3】多参构造创建实例(int:88,非泛型int:1000)
【构造函数】GenericTestClass<Int32> 多参构造执行,泛型值:88,非泛型值:1000
- GenericProperty值:88
- NonGenericProperty值:1000
【扩展】绑定string类型,单参构造(参数:"Hello Reflection")
【构造函数】GenericTestClass<String> 单参构造执行,初始值:Hello Reflection
- String类型实例的GenericProperty:Hello Reflection
【异常演示】构造函数参数类型不匹配(int类型实例传string参数)
- 异常信息:Object of type 'System.String' cannot be converted to type 'System.Int32'.
核心说明:
Activator.CreateInstance(Type, params object[])是创建实例的核心方法,第二个参数是构造函数的参数数组;- 构造函数参数类型必须与已绑定类型的泛型参数匹配,否则会抛出
TargetInvocationException(内层是类型转换异常); - 强转(
as GenericTestClass<int>)是反射后使用实例的常用方式,前提是知道泛型参数类型。
3.3 场景 3:动态调用泛型实例方法(含重载)
目标:掌握 "泛型方法定义" 的获取、方法级泛型参数的绑定、实例方法的调用。
cs
/// <summary>
/// 场景3:动态调用泛型实例方法(含方法级泛型参数绑定)
/// </summary>
static void Scene3_CallGenericInstanceMethod()
{
// 步骤1:创建泛型类实例(绑定int类型,单参构造:100)
Type boundType_Int = typeof(GenericTestClass<int>);
object instance = Activator.CreateInstance(boundType_Int, 100);
// 子场景1:调用非泛型实例方法(基础)
Console.WriteLine("【子场景1】调用非泛型实例方法");
MethodInfo nonGenericMethod = boundType_Int.GetMethod("NonGenericInstanceMethod");
nonGenericMethod.Invoke(instance, null); // 第二个参数:方法参数数组(无参则传null)
// 子场景2:调用泛型实例方法(单泛型参数U)
Console.WriteLine("\n【子场景2】调用泛型实例方法GenericInstanceMethod<U>(绑定U为string)");
// 步骤1:获取泛型方法定义(未绑定方法)
MethodInfo genericMethodDef = boundType_Int.GetMethod("GenericInstanceMethod");
Console.WriteLine($" - 方法是否是泛型定义:{genericMethodDef.IsGenericMethodDefinition}"); // true
Console.WriteLine($" - 方法泛型形参数量:{genericMethodDef.GetGenericArguments().Length}"); // 1(U)
// 步骤2:绑定方法级泛型参数(U→string)
MethodInfo boundMethod = genericMethodDef.MakeGenericMethod(typeof(string));
Console.WriteLine($" - 绑定后的方法名:{boundMethod.Name}");
// 步骤3:调用方法(参数数组:input1=100(T=int),input2="测试字符串"(U=string))
boundMethod.Invoke(instance, new object[] { 100, "测试字符串" });
// 子场景3:调用重载的泛型实例方法(U+V两个泛型参数)
Console.WriteLine("\n【子场景3】调用重载泛型实例方法GenericInstanceMethod<U,V>(U=double,V=DateTime)");
// 注意:GetMethod默认获取第一个匹配名称的方法,重载需指定参数类型(场景8详解)
MethodInfo genericMethodDef_Overload = boundType_Int.GetMethod(
"GenericInstanceMethod",
new Type[] { typeof(int), typeof(object), typeof(object) } // 参数类型:T=int, U=object, V=object(临时占位)
);
// 绑定方法泛型参数:U=double,V=DateTime
MethodInfo boundMethod_Overload = genericMethodDef_Overload.MakeGenericMethod(typeof(double), typeof(DateTime));
// 调用方法:input1=200(int),input2=3.14(double),input3=当前时间(DateTime)
boundMethod_Overload.Invoke(instance, new object[] { 200, 3.14, DateTime.Now });
}
运行结果:
cs
【构造函数】GenericTestClass<Int32> 单参构造执行,初始值:100
【子场景1】调用非泛型实例方法
【实例方法】非泛型方法执行,泛型类型:Int32,GenericProperty值:100
【子场景2】调用泛型实例方法GenericInstanceMethod<U>(绑定U为string)
- 方法是否是泛型定义:True
- 方法泛型形参数量:1
- 绑定后的方法名:GenericInstanceMethod
【实例方法】泛型方法<String>执行,输入1(Int32):100,输入2(String):测试字符串
【子场景3】调用重载泛型实例方法GenericInstanceMethod<U,V>(U=double,V=DateTime)
【实例方法】泛型方法<Double,DateTime>重载版执行,输入1:200,输入2:3.14,输入3:2025/12/16 15:30:00
核心说明:
- 泛型方法的操作分三步:获取方法定义→绑定方法级泛型参数→调用(
Invoke); MethodInfo.Invoke(object instance, object[] parameters):- 第一个参数:实例方法传实例,静态方法传
null; - 第二个参数:方法参数数组,顺序必须与方法定义一致;
- 第一个参数:实例方法传实例,静态方法传
- 重载方法的精准获取需指定参数类型(场景 8 详解)。
3.4 场景 4:动态调用泛型静态方法
目标:掌握静态泛型方法的获取、绑定、调用(无需实例)。
cs
/// <summary>
/// 场景4:动态调用泛型静态方法(无需创建实例)
/// </summary>
static void Scene4_CallGenericStaticMethod()
{
// 步骤1:获取已绑定类型(int)
Type boundType_Int = typeof(GenericTestClass<int>);
// 子场景1:调用非泛型静态方法
Console.WriteLine("【子场景1】调用非泛型静态方法");
MethodInfo nonGenericStaticMethod = boundType_Int.GetMethod("NonGenericStaticMethod");
nonGenericStaticMethod.Invoke(null, new object[] { "静态方法测试消息" }); // 实例参数传null
// 子场景2:调用泛型静态方法
Console.WriteLine("\n【子场景2】调用泛型静态方法GenericStaticMethod<W>(绑定W为bool)");
// 步骤1:获取泛型静态方法定义
MethodInfo genericStaticMethodDef = boundType_Int.GetMethod("GenericStaticMethod");
Console.WriteLine($" - 是否是泛型方法定义:{genericStaticMethodDef.IsGenericMethodDefinition}"); // true
// 步骤2:绑定方法泛型参数W→bool
MethodInfo boundStaticMethod = genericStaticMethodDef.MakeGenericMethod(typeof(bool));
// 步骤3:调用静态方法(实例参数null,方法参数:true)
boundStaticMethod.Invoke(null, new object[] { true });
// 扩展:绑定不同泛型参数(W=DateTime)
Console.WriteLine("\n【扩展】绑定W=DateTime调用泛型静态方法");
MethodInfo boundStaticMethod_DateTime = genericStaticMethodDef.MakeGenericMethod(typeof(DateTime));
boundStaticMethod_DateTime.Invoke(null, new object[] { DateTime.Now });
}
运行结果:
cs
【子场景1】调用非泛型静态方法
【静态方法】非泛型静态方法执行,消息:静态方法测试消息
【子场景2】调用泛型静态方法GenericStaticMethod<W>(绑定W为bool)
- 是否是泛型方法定义:True
【静态方法】泛型静态方法<Boolean>执行,值:True
【扩展】绑定W=DateTime调用泛型静态方法
【静态方法】泛型静态方法<DateTime>执行,值:2025/12/16 15:30:00
核心说明:
- 静态方法调用时,
Invoke的第一个参数必须传null; - 泛型静态方法的绑定逻辑与实例泛型方法一致,区别仅在于 "无需实例";
- 静态方法属于类型本身,与实例无关,因此无需创建泛型类实例。
3.5 场景 5:反射操作泛型字段 / 属性
目标:掌握泛型类型的字段、属性的读取和修改,解决 "动态访问泛型成员" 问题。
cs
/// <summary>
/// 场景5:反射操作泛型字段/属性(读取/修改)
/// </summary>
static void Scene5_ReflectGenericFieldProperty()
{
// 步骤1:创建泛型实例(绑定string类型,单参构造:"初始值")
Type boundType_String = typeof(GenericTestClass<string>);
object instance = Activator.CreateInstance(boundType_String, "初始值");
// 子场景1:操作泛型字段GenericField
Console.WriteLine("【子场景1】操作泛型字段GenericField");
FieldInfo genericField = boundType_String.GetField("GenericField");
// 读取字段值
object fieldValue = genericField.GetValue(instance);
Console.WriteLine($" - 原始字段值:{fieldValue}");
// 修改字段值
genericField.SetValue(instance, "修改后的字段值");
Console.WriteLine($" - 修改后的字段值:{genericField.GetValue(instance)}");
// 子场景2:操作泛型属性GenericProperty
Console.WriteLine("\n【子场景2】操作泛型属性GenericProperty");
PropertyInfo genericProperty = boundType_String.GetProperty("GenericProperty");
// 读取属性值
object propValue = genericProperty.GetValue(instance);
Console.WriteLine($" - 原始属性值:{propValue}");
// 修改属性值
genericProperty.SetValue(instance, "修改后的属性值");
Console.WriteLine($" - 修改后的属性值:{genericProperty.GetValue(instance)}");
// 子场景3:操作非泛型属性NonGenericProperty
Console.WriteLine("\n【子场景3】操作非泛型属性NonGenericProperty");
PropertyInfo nonGenericProp = boundType_String.GetProperty("NonGenericProperty");
Console.WriteLine($" - 原始值:{nonGenericProp.GetValue(instance)}"); // 默认0
nonGenericProp.SetValue(instance, 999);
Console.WriteLine($" - 修改后值:{nonGenericProp.GetValue(instance)}"); // 999
// 异常场景:字段/属性不存在
try
{
Console.WriteLine("\n【异常演示】获取不存在的字段");
boundType_String.GetField("不存在的字段");
}
catch (NullReferenceException ex)
{
Console.WriteLine($" - 异常:{ex.Message}");
}
}
运行结果:
cs
【构造函数】GenericTestClass<String> 单参构造执行,初始值:初始值
【子场景1】操作泛型字段GenericField
- 原始字段值:初始值
- 修改后的字段值:修改后的字段值
【子场景2】操作泛型属性GenericProperty
- 原始属性值:初始值
- 修改后的属性值:修改后的属性值
【子场景3】操作非泛型属性NonGenericProperty
- 原始值:0
- 修改后值:999
【异常演示】获取不存在的字段
- 异常:Object reference not set to an instance of an object.
核心说明:
FieldInfo.GetValue(object)/SetValue(object, object):读取 / 修改字段值,参数为实例和新值;PropertyInfo.GetValue(object)/SetValue(object, object):读取 / 修改属性值,逻辑与字段一致;- 泛型字段 / 属性的类型由已绑定类型的泛型参数决定(如绑定 string 则字段类型为 string);
- 获取成员时名称必须完全匹配(区分大小写),否则返回
null,调用GetValue会抛空引用异常。
3.6 场景 6:泛型接口的反射操作
目标:掌握泛型接口的获取、接口方法的调用、实现类的反射。
cs
/// <summary>
/// 场景6:泛型接口的反射操作(获取接口、调用接口方法)
/// </summary>
static void Scene6_ReflectGenericInterface()
{
// 步骤1:获取泛型接口实现类的已绑定类型(绑定double)
Type implementType_Double = typeof(GenericInterfaceImplement<double>);
// 子场景1:检查实现类是否实现泛型接口
Console.WriteLine("【子场景1】检查实现类是否实现泛型接口");
// 获取接口类型:GetInterface("接口名`泛型参数个数"),`1表示1个泛型参数
Type genericInterfaceType = implementType_Double.GetInterface("IGenericTestInterface`1");
Console.WriteLine($" - 是否实现IGenericTestInterface<T>:{genericInterfaceType != null}"); // true
Console.WriteLine($" - 接口泛型实参:{genericInterfaceType.GetGenericArguments()[0].Name}"); // Double
// 子场景2:创建实现类实例并调用接口方法
Console.WriteLine("\n【子场景2】调用泛型接口方法");
object instance = Activator.CreateInstance(implementType_Double);
// 调用SetData方法
MethodInfo setDataMethod = genericInterfaceType.GetMethod("SetData");
setDataMethod.Invoke(instance, new object[] { 3.1415926 }); // 参数:double类型的π
// 调用GetData方法
MethodInfo getDataMethod = genericInterfaceType.GetMethod("GetData");
object data = getDataMethod.Invoke(instance, null);
Console.WriteLine($" - GetData返回值:{data}");
// 调用接口的泛型方法GenericInterfaceMethod<U>
Console.WriteLine("\n【子场景3】调用接口的泛型方法");
MethodInfo interfaceGenericMethodDef = genericInterfaceType.GetMethod("GenericInterfaceMethod");
// 绑定方法泛型参数U为string
MethodInfo boundInterfaceMethod = interfaceGenericMethodDef.MakeGenericMethod(typeof(string));
// 调用方法:input=2.718(double),output="自然常数e"(string)
boundInterfaceMethod.Invoke(instance, new object[] { 2.718, "自然常数e" });
}
运行结果:
cs
【子场景1】检查实现类是否实现泛型接口
- 是否实现IGenericTestInterface<T>:True
- 接口泛型实参:Double
【子场景2】调用泛型接口方法
【接口实现】SetData()执行,设置值:3.1415926
【接口实现】GetData()执行,返回值:3.1415926
- GetData返回值:3.1415926
【子场景3】调用接口的泛型方法
【接口实现】泛型接口方法<String>执行,输入:2.718,输出:自然常数e
核心说明:
- 获取泛型接口需使用
GetInterface("接口名泛型参数个数 ")(如IGenericTestInterface1),1表示接口有 1 个泛型参数; - 泛型接口的方法调用逻辑与泛型类方法一致,区别在于 "方法定义来自接口类型";
- 实现类的泛型参数会自动传递给接口的泛型参数(如
GenericInterfaceImplement<double>→IGenericTestInterface<double>)。
3.7 场景 7:嵌套泛型的反射处理
目标 :掌握嵌套泛型(如List<Dictionary<int, string>>)的反射,解决复杂泛型类型的操作问题。
cs
/// <summary>
/// 场景7:处理嵌套泛型(如List<Dictionary<int, string>>)
/// </summary>
static void Scene7_HandleNestedGeneric()
{
// 需求:动态创建List<Dictionary<int, string>>并添加元素
// 步骤1:定义嵌套泛型的层级
// 内层:Dictionary<int, string>
Type dictGenericDef = typeof(Dictionary<,>); // 2个泛型参数
Type dictBoundType = dictGenericDef.MakeGenericType(typeof(int), typeof(string));
// 外层:List<Dictionary<int, string>>
Type listGenericDef = typeof(List<>); // 1个泛型参数
Type listBoundType = listGenericDef.MakeGenericType(dictBoundType);
Console.WriteLine($"嵌套泛型类型名:{listBoundType.FullName}");
// 步骤2:创建List实例
object listInstance = Activator.CreateInstance(listBoundType);
Console.WriteLine($"List实例类型:{listInstance.GetType().Name}");
// 步骤3:创建Dictionary实例并添加元素
object dictInstance = Activator.CreateInstance(dictBoundType);
// 调用Dictionary的Add方法(key=1,value="Apple")
MethodInfo dictAddMethod = dictBoundType.GetMethod("Add");
dictAddMethod.Invoke(dictInstance, new object[] { 1, "Apple" });
dictAddMethod.Invoke(dictInstance, new object[] { 2, "Banana" });
// 步骤4:将Dictionary添加到List中
MethodInfo listAddMethod = listBoundType.GetMethod("Add");
listAddMethod.Invoke(listInstance, new object[] { dictInstance });
// 步骤5:验证List的Count属性
PropertyInfo listCountProp = listBoundType.GetProperty("Count");
int count = (int)listCountProp.GetValue(listInstance);
Console.WriteLine($"List<Dictionary<int,string>>的元素个数:{count}");
// 步骤6:读取Dictionary的元素(扩展)
MethodInfo dictTryGetValueMethod = dictBoundType.GetMethod("TryGetValue");
object[] tryGetValueParams = new object[] { 1, null }; // out参数初始为null
bool success = (bool)dictTryGetValueMethod.Invoke(dictInstance, tryGetValueParams);
if (success)
{
Console.WriteLine($"Dictionary中key=1的值:{tryGetValueParams[1]}"); // out参数在索引1
}
}
运行结果:
cs
嵌套泛型类型名:System.Collections.Generic.List`1[[System.Collections.Generic.Dictionary`2[[System.Int32, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]
List实例类型:List`1
List<Dictionary<int,string>>的元素个数:1
Dictionary中key=1的值:Apple
核心说明:
- 嵌套泛型的处理需 "从内到外" 绑定泛型参数:先绑定内层(Dictionary),再绑定外层(List);
out参数的处理:调用方法时需传入长度匹配的数组,out参数的值会填充到数组对应位置;- 嵌套泛型是框架开发的高频场景(如 ORM 的
IQueryable<Dictionary<string, object>>)。
3.8 场景 8:泛型方法重载的精准获取
目标:解决 "泛型方法重载时 GetMethod 获取错误方法" 的问题,掌握 "参数类型匹配" 的精准获取方式。
cs
/// <summary>
/// 场景8:精准获取重载的泛型方法(解决GetMethod默认获取第一个匹配方法的问题)
/// </summary>
static void Scene8_GetOverloadGenericMethod()
{
// 步骤1:获取已绑定类型(int)
Type boundType_Int = typeof(GenericTestClass<int>);
// 问题:GenericInstanceMethod有两个重载(1个参数泛型/2个参数泛型),默认GetMethod会获取第一个
// 解决:通过参数类型数组精准匹配
Console.WriteLine("【子场景1】获取单参数泛型方法(GenericInstanceMethod<U>(T, U))");
// 参数类型数组:T=int,U=object(方法参数的类型,U是泛型参数,临时用object占位)
Type[] singleParamMethodTypes = new Type[] { typeof(int), typeof(object) };
MethodInfo singleParamGenericMethod = boundType_Int.GetMethod(
"GenericInstanceMethod",
singleParamMethodTypes
);
Console.WriteLine($" - 方法是否是泛型定义:{singleParamGenericMethod.IsGenericMethodDefinition}");
Console.WriteLine($" - 方法参数个数:{singleParamGenericMethod.GetParameters().Length}"); // 2个参数(T, U)
// 绑定U为DateTime并调用
MethodInfo boundSingleMethod = singleParamGenericMethod.MakeGenericMethod(typeof(DateTime));
object instance = Activator.CreateInstance(boundType_Int, 500);
boundSingleMethod.Invoke(instance, new object[] { 500, DateTime.Now });
Console.WriteLine("\n【子场景2】获取双参数泛型方法(GenericInstanceMethod<U,V>(T, U, V))");
// 参数类型数组:T=int,U=object,V=object
Type[] doubleParamMethodTypes = new Type[] { typeof(int), typeof(object), typeof(object) };
MethodInfo doubleParamGenericMethod = boundType_Int.GetMethod(
"GenericInstanceMethod",
doubleParamMethodTypes
);
Console.WriteLine($" - 方法参数个数:{doubleParamGenericMethod.GetParameters().Length}"); // 3个参数(T, U, V)
// 绑定U=float,V=Guid并调用
MethodInfo boundDoubleMethod = doubleParamGenericMethod.MakeGenericMethod(typeof(float), typeof(Guid));
boundDoubleMethod.Invoke(instance, new object[] { 600, 1.23f, Guid.NewGuid() });
}
}
}
运行结果:
cs
【子场景1】获取单参数泛型方法(GenericInstanceMethod<U>(T, U))
- 方法是否是泛型定义:True
- 方法参数个数:2
【构造函数】GenericTestClass<Int32> 单参构造执行,初始值:500
【实例方法】泛型方法<DateTime>执行,输入1(Int32):500,输入2(DateTime):2025/12/16 15:30:00
【子场景2】获取双参数泛型方法(GenericInstanceMethod<U,V>(T, U, V))
- 方法参数个数:3
【实例方法】泛型方法<Single,Guid>重载版执行,输入1:600,输入2:1.23,输入3:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
核心说明:
- 泛型方法重载的区分核心是 "参数个数 + 参数类型";
- 方法级泛型参数(如 U、V)在获取方法时需用
object占位,绑定泛型参数后再传入具体类型; - 若重载方法的参数类型不同(如
intvsstring),需精准指定参数类型数组,避免获取错误方法。
四、反射操作泛型的底层原理与性能优化
4.1 底层原理
- 泛型类型在 CLR 中是 "模板生成":每个不同的泛型参数绑定(如
GenericClass<int>、GenericClass<string>)会生成独立的 IL 代码; - 反射操作泛型的本质是 "运行时解析泛型元数据":CLR 维护了泛型类型的元数据(泛型定义、参数、方法),反射 API 通过读取这些元数据实现动态操作;
MakeGenericType的底层是 "绑定泛型参数到元数据模板,生成新的 Type 对象"。
4.2 性能优化
反射操作的性能远低于静态调用,高频场景需优化:
缓存核心对象 :缓存Type、MethodInfo、PropertyInfo等对象,避免重复调用GetType()/GetMethod();
cs
// 示例:缓存泛型方法定义
private static readonly MethodInfo _cachedGenericMethod = typeof(GenericTestClass<int>).GetMethod("GenericInstanceMethod");
- 使用 Delegate 减少 Invoke 开销 :将
MethodInfo转换为强类型委托,避免每次Invoke的反射开销; - 避免频繁创建实例 :复用泛型实例,减少
Activator.CreateInstance的调用; - 使用表达式树(Expression)替代反射:对于高频调用的泛型方法,可通过表达式树动态生成委托,性能接近静态调用。
五、避坑指南(常见错误与解决方案)
|--------------------------------------------|-------------------------------------------------------------|---------------------------------------------------|
| 常见错误 | | 原因 | |----| | 解决方案 |
| MakeGenericType 传入参数个数不匹配 | 泛型定义的形参个数与传入的实参个数不一致(如<T>传 2 个类型) | 检查typeof(类名<>)的泛型参数个数,确保MakeGenericType参数个数匹配 |
| Invoke 抛出TargetParameterCountException | 方法参数数组长度与方法定义的参数个数不一致 | 核对方法参数个数,确保Invoke的第二个参数数组长度匹配 |
| Invoke 抛出ArgumentException | 参数类型与方法定义的参数类型不匹配(如 int 传 string) | |---------------------| | 确保参数类型与已绑定类型的泛型参数一致 | |
| GetMethod 返回null | 方法名错误 / 重载匹配失败 / 非公共方法(默认 GetMethod 只获取公共方法) | 检查方法名大小写 / 指定参数类型数组 / 使用BindingFlags获取非公共方法 |
| 泛型接口获取失败 | 接口名未加泛型参数个数(如IGenericInterface而非IGenericInterface1`) | 使用GetInterface("接口名参数个数 ")` |