使用Type.MakeGenericType,反射构造泛型类型

有时我们会有通过反射来动态构造泛型类型的需求,该如何实现呢?举个栗子,比如我们常常定义的泛型委托Func<in T, out TResult>,当T或TResult的类型需要根据程序上下文来确定时,也就是说我们的泛型委托类型是动态确定的,那么如何来构造呢?答案就是typeof(Func<,>).MakeGenericType(typeof(T), typeof(TResult))

一、先来看下Type.MakeGenericType的描述。

// C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll
namespace System
{
        //
        // 摘要:
        //     替代由当前泛型类型定义的类型参数组成的类型数组的元素,并返回表示结果构造类型的 System.Type 对象。
        //
        // 参数:
        //   typeArguments:
        //     将代替当前泛型类型的类型参数的类型数组。
        //
        // 返回结果:
        //     System.Type 表示的构造类型通过以下方式形成:用 typeArguments 的元素取代当前泛型类型的类型参数。
        //
        // 异常:
        //   T:System.InvalidOperationException:
        //     当前的类型不表示泛型类型定义。也就是说, System.Type.IsGenericTypeDefinition 返回 false。
        //
        //   T:System.ArgumentNullException:
        //     typeArguments 为 null。- 或 - 任何元素 typeArguments 是 null。
        //
        //   T:System.ArgumentException:
        //     中的元素数 typeArguments 不是当前的泛型类型定义中的类型参数的编号相同。- 或 - 任何元素 typeArguments 不满足当前的泛型类型的相应类型参数指定的约束。-
        //     或 - typeArguments 包含的元素,是指针类型 (System.Type.IsPointer 返回 true),通过 ref 类型 (System.Type.IsByRef
        //     返回 true),或 System.Void。
        //
        //   T:System.NotSupportedException:
        //     在基类中不支持调用的方法。派生类必须提供一个实现。
        public virtual Type MakeGenericType(params Type[] typeArguments);
}

二、示例

通过MakeGenericType方法,从Func<T,TResult>泛型委托类型创建出特定类型Func<string,Object>的委托类型。

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("\r\n--- 通过基本的泛型委托类型构造特定类型的委托类型。");
            
            //创建一个类型对象,表示基本的泛型委托类型。
            //要省略类型参数(但保留类型参数之间的逗号,使编译器能够推断出参数数量)。
            Type generic = typeof(Func<,>);
            DisplayTypeInfo(generic);
            
            //创建类型数组以替代泛型委托的类型参数,
            //输入参数类型为string,输出参数类型为Object。
            Type[] typeArgs = { typeof(string), typeof(Object) };
            
            //创建特定类型的泛型委托类型对象
            Type constructed = generic.MakeGenericType(typeArgs);
            DisplayTypeInfo(constructed);

            //再通过typeof()直接创建一个类型对象
            Type t = typeof(Func<String, Object>);

            Console.WriteLine("\r\n--- 比较两种方法得到的类型:");
            Console.WriteLine("\t两种类型是否相等? {0}", t == constructed);
            Console.WriteLine("\t两种类型的泛型类型定义是否相等? {0}",t.GetGenericTypeDefinition() == generic);
            Console.Read();
        }
        private static void DisplayTypeInfo(Type t)
        {
            Console.WriteLine("\r\n{0}", t);
            Console.WriteLine("\t是否泛型类型定义? {0}",t.IsGenericTypeDefinition);
            Console.WriteLine("\t是否泛型类型? {0}",t.IsGenericType);

            Type[] typeArguments = t.GetGenericArguments();
            Console.WriteLine("\t枚举类型参数 ({0}):", typeArguments.Length);
            foreach (Type tParam in typeArguments)
            {
                Console.WriteLine("\t\t{0}", tParam);
            }
        }
    }

输出
524552-20180427172641934-2115979915.png

转载于:https://www.cnblogs.com/jiujiduilie/p/8654576.html

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java 17中,可以使用反射来获取泛型类。面是一种常见的方法: 1. 首先,通过反射获取目标类的Class对象。假设目标类为`MyClass`,可以使用`MyClass.class`或者`Class.forName("com.example.MyClass")`来获取。 2. 使用`getDeclaredField`方法获取目标字段的Field对象。假设目标字段为`myField`,可以使用`Class.getDeclaredField("myField")`来获取。 3. 通过Field对象的`getGenericType`方法获取字段的泛型类。这将返回一个Type对象,表示字段的实际类。 4. 如果字段的类是参数化类(即包含泛参数),可以通过Type对象的一些方法来获取泛参数的信息。例如,可以使用`ParameterizedType`接口来获取参数化类的原始类和泛参数列表。 下面是一个示例代码,演示了如何使用反射获取泛型类: ```java import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public class Main { public static void main(String[] args) throws NoSuchFieldException { // 获取目标类的Class对象 Class<MyClass> clazz = MyClass.class; // 获取目标字段的Field对象 Field field = clazz.getDeclaredField("myField"); // 获取字段的泛型类 Type fieldType = field.getGenericType(); // 如果字段的类是参数化类 if (fieldType instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) fieldType; // 获取参数化类的原始类 Type rawType = parameterizedType.getRawType(); System.out.println("Raw type: " + rawType); // 获取参数化类的泛参数列表 Type[] typeArguments = parameterizedType.getActualTypeArguments(); for (Type typeArgument : typeArguments) { System.out.println("Type argument: " + typeArgument); } } } } class MyClass { private List<String> myField; } ``` 在上面的示例中,我们通过反射获取了`MyClass`类中名为`myField`的字段的泛型类。输出结果如下: ``` Raw type: interface java.util.List Type argument: class java.lang.String ``` 这表明`myField`字段的类是`List<String>`,其中`List`是原始类,`String`是泛参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值