使用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);
            }
        }
    }
输出

使用Type.MakeGenericType,反射构造泛型类型的更多相关文章
- Type.MakeGenericType 方法 (Type[]) 泛型反射
		替代由当前泛型类型定义的类型参数组成的类型数组的元素,并返回表示结果构造类型的 Type 对象. 命名空间: System程序集: mscorlib(mscorlib.dll 中) public ... 
- Python面向对象06 /元类type、反射、函数与类的区别、特殊的双下方法
		Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3 ... 
- python 面向对象专题(六):元类type、反射、函数与类的区别、特殊的双下方法
		目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3. 函数与类的区别 4. 特殊的双下方法 1. 元类type type:获取对象 ... 
- java学习:用反射构造bean
		先贴一些反射的基本知识:-------------------------------------------------------------------- 一.什么是反射:反射的概念是由Smit ... 
- java 利用反射构造泛型类
		1.构造BaseDao泛型类 class BaseDao<T>{ private Class<T> entityClass; // 通过反射获取实际运行的精确类 public ... 
- Java反射获取泛型类型
		本文链接:https://blog.csdn.net/hongxingxiaonan/article/details/49202613 在Java反射技术的应用中,取得一个类的成员.方法和构造函数相对 ... 
- Java 反射 -- 获取泛型类型
		先写一个类: public class Demo03 { public void test01(Map<String, User> map, List<User> list) ... 
- python---issubclass/type/isinstance/ 反射(内置函数getattr/delattr...)
		# 一 python面向对象-内置函数(issubclass(), type(), isinstance()) # issubclass 判断xxxx类是否是xxxx类的子类 class egg: p ... 
- day17 isinstance type issubclass 反射
		1. issubclass,type,isinstance 1.issubclass 判断xxx是否yyy的子类 例: class Foo: pass class Bar(Foo): pass cla ... 
随机推荐
- element-ui和npm、webpack、vue-cli搭建Vue项目
			一.element-ui的简单使用 1.安装 1. npm 安装 推荐使用 npm 的方式安装,它能更好地和 webpack 打包工具配合使用. npm i element-ui -S 2. CDN ... 
- virtualBox centos 6.5 硬盘扩容
			1. 操作virtual Box 将该虚拟机关机,然后将打开管理->介质管理 调整硬盘大小 2. 操作Linux 1. 将放大的进行分区建立 2. 将分区建立分区表 3. 将该分区合并到root ... 
- 51nod1812树的双直径(换根树DP)
			传送门:http://www.51nod.com/Challenge/Problem.html#!#problemId=1812 题解:头一次写换根树DP. 求两条不相交的直径乘积最大,所以可以这样考 ... 
- Harbo1.5.2离线搭建
			环境说明 操作系统版本:Centos7.5 docker版本:docker-ce 17.03.2 harbor版本:v1.5.2 docker-compose: 1.22.0 基础环境搭建 系统优化 ... 
- 2018-2019-2 实验一 Java开发环境的熟悉
			实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用IDEA编辑.编译.运行.调试Java程序 实验知识点 1. JVM.JRE.JDK的安装位置与区别: 2. 命令行运行javac:ja ... 
- 第十一节:Bundles压缩合并js和css及原理分析
			一. 简介 1.背景:浏览器默认一次性请求的网络数是有上限的,如果你得js和css文件太多,就会导致浏览器需要多次加载,影响页面的加载速度, MVC中提供Bundles的方式压缩合并js和css,是M ... 
- 常用的消息队列中间件mq对比
			原文地址:https://blog.csdn.net/qq_30764991/article/details/80239076 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量 ... 
- [物理学与PDEs]第5章第3节 守恒定律, 应力张量
			5. 3 守恒定律, 应力张量 5. 3. 1 质量守恒定律 $$\bex \cfrac{\p \rho}{\p t}+\Div_y(\rho{\bf v})=0. \eex$$ 5. 3. 2 应 ... 
- $m$ 整除 $10^k$ 的一个充分条件
			若 (1) 既约分数 $\cfrac{n}{m}$ 满足 $0<\cfrac{n}{m}<1$; (2) 分数 $\cfrac{n}{m}$ 可以化为小数部分的一个循环节有 $k$ 位数字 ... 
- Eclipse中的sysout与debug-遁地龙卷风
			(-1)调试 在读<<一个程序员的奋斗史>>时里面提到这是一件很low的事情,突然想到自己也一直用sysout, 我是一个有情怀的人! (0)sysout的坏处 之所以长久的使 ... 
