zoukankan      html  css  js  c++  java
  • 使用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);
                }
            }
        }
    

    输出

  • 相关阅读:
    记录某次应急演练
    C++之分文件编写
    C++之冒泡排序实现
    cobaitstrike之修改特征
    cobaitstrike之DNS上线
    网盘搜索【不断更新ing】
    CVE-2021-2109 Weblogic Server远程代码执行
    C++之一维&二维数组
    CDH-5.12.2安装教程
    linux安装mysql教程
  • 原文地址:https://www.cnblogs.com/jiujiduilie/p/8654576.html
Copyright © 2011-2022 走看看