中山市网站建设_网站建设公司_色彩搭配_seo优化
2025/12/17 3:56:16 网站建设 项目流程

反射(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 准备测试用泛型类型(基础依赖)

先定义一套覆盖 “泛型类、泛型接口、泛型方法(实例 / 静态 / 重载)、泛型属性 / 字段” 的测试类型,后续所有反射操作均基于此:

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:泛型类型的反射基础操作

目标:掌握 “泛型定义” 与 “已绑定类型” 的区分、核心属性判断、泛型参数获取。

/// <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 }

运行结果

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:动态创建泛型类实例(全构造函数)

目标:掌握无参、单参、多参构造函数的泛型实例创建,解决 “构造函数参数匹配” 问题。

/// <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 } }

运行结果

【子场景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:动态调用泛型实例方法(含重载)

目标:掌握 “泛型方法定义” 的获取、方法级泛型参数的绑定、实例方法的调用。

/// <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 }); }

运行结果

【构造函数】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:动态调用泛型静态方法

目标:掌握静态泛型方法的获取、绑定、调用(无需实例)。

/// <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 }); }

运行结果

【子场景1】调用非泛型静态方法 【静态方法】非泛型静态方法执行,消息:静态方法测试消息 【子场景2】调用泛型静态方法GenericStaticMethod<W>(绑定W为bool) - 是否是泛型方法定义:True 【静态方法】泛型静态方法<Boolean>执行,值:True 【扩展】绑定W=DateTime调用泛型静态方法 【静态方法】泛型静态方法<DateTime>执行,值:2025/12/16 15:30:00

核心说明

  • 静态方法调用时,Invoke的第一个参数必须传null
  • 泛型静态方法的绑定逻辑与实例泛型方法一致,区别仅在于 “无需实例”;
  • 静态方法属于类型本身,与实例无关,因此无需创建泛型类实例。

3.5 场景 5:反射操作泛型字段 / 属性

目标:掌握泛型类型的字段、属性的读取和修改,解决 “动态访问泛型成员” 问题。

/// <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}"); } }

运行结果

【构造函数】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:泛型接口的反射操作

目标:掌握泛型接口的获取、接口方法的调用、实现类的反射。

/// <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" }); }

运行结果

【子场景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>>)的反射,解决复杂泛型类型的操作问题。

/// <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 } }

运行结果

嵌套泛型类型名: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 获取错误方法” 的问题,掌握 “参数类型匹配” 的精准获取方式。

/// <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() }); } } }

运行结果

【子场景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 性能优化

反射操作的性能远低于静态调用,高频场景需优化:

缓存核心对象:缓存TypeMethodInfoPropertyInfo等对象,避免重复调用GetType()/GetMethod()

// 示例:缓存泛型方法定义 private static readonly MethodInfo _cachedGenericMethod = typeof(GenericTestClass<int>).GetMethod("GenericInstanceMethod");
  1. 使用 Delegate 减少 Invoke 开销:将MethodInfo转换为强类型委托,避免每次Invoke的反射开销;
  2. 避免频繁创建实例:复用泛型实例,减少Activator.CreateInstance的调用;
  3. 使用表达式树(Expression)替代反射:对于高频调用的泛型方法,可通过表达式树动态生成委托,性能接近静态调用。

五、避坑指南(常见错误与解决方案)

常见错误
原因
解决方案
MakeGenericType传入参数个数不匹配泛型定义的形参个数与传入的实参个数不一致(如<T>传 2 个类型)检查typeof(类名<>)的泛型参数个数,确保MakeGenericType参数个数匹配
Invoke抛出TargetParameterCountException方法参数数组长度与方法定义的参数个数不一致核对方法参数个数,确保Invoke的第二个参数数组长度匹配
Invoke抛出ArgumentException参数类型与方法定义的参数类型不匹配(如 int 传 string)
确保参数类型与已绑定类型的泛型参数一致
GetMethod返回null方法名错误 / 重载匹配失败 / 非公共方法(默认 GetMethod 只获取公共方法)检查方法名大小写 / 指定参数类型数组 / 使用BindingFlags获取非公共方法
泛型接口获取失败接口名未加泛型参数个数(如IGenericInterface而非IGenericInterface1`)使用GetInterface("接口名参数个数 ")`

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询