有时我们会有通过反射来动态构造泛型类型的需求,该如何实现呢?举个栗子,比如我们常常定义的泛型委托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,反射构造泛型类型的更多相关文章

  1. Type.MakeGenericType 方法 (Type[]) 泛型反射

    替代由当前泛型类型定义的类型参数组成的类型数组的元素,并返回表示结果构造类型的 Type 对象. 命名空间:   System程序集:  mscorlib(mscorlib.dll 中) public ...

  2. Python面向对象06 /元类type、反射、函数与类的区别、特殊的双下方法

    Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3 ...

  3. python 面向对象专题(六):元类type、反射、函数与类的区别、特殊的双下方法

    目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3. 函数与类的区别 4. 特殊的双下方法 1. 元类type type:获取对象 ...

  4. java学习:用反射构造bean

    先贴一些反射的基本知识:-------------------------------------------------------------------- 一.什么是反射:反射的概念是由Smit ...

  5. java 利用反射构造泛型类

    1.构造BaseDao泛型类 class BaseDao<T>{ private Class<T> entityClass; // 通过反射获取实际运行的精确类 public ...

  6. Java反射获取泛型类型

    本文链接:https://blog.csdn.net/hongxingxiaonan/article/details/49202613 在Java反射技术的应用中,取得一个类的成员.方法和构造函数相对 ...

  7. Java 反射 -- 获取泛型类型

    先写一个类: public class Demo03 { public void test01(Map<String, User> map, List<User> list) ...

  8. python---issubclass/type/isinstance/ 反射(内置函数getattr/delattr...)

    # 一 python面向对象-内置函数(issubclass(), type(), isinstance()) # issubclass 判断xxxx类是否是xxxx类的子类 class egg: p ...

  9. day17 isinstance type issubclass 反射

    1. issubclass,type,isinstance 1.issubclass 判断xxx是否yyy的子类 例: class Foo: pass class Bar(Foo): pass cla ...

随机推荐

  1. Vim简明学习

    前面的话 在linux云服务器上的编辑器默认是vim,类似于windows系统中的记事本,页面简洁,但入门不易.本文将介绍Vim的基础使用 操作模式 vim编辑器有三种模式: 1.命令模式(等待用户输 ...

  2. Flask的插件session、SQLAlchemy、Script、Migrate

    一.flask-session 1.为什么要使用flask-session 因为flask默认的session是通过请求上下文放入到Local中的,是存在内存的,而使用flask-session可以更 ...

  3. P1033 自由落体

    原题链接 https://www.luogu.org/problemnew/show/P1033 不得不说,这个题太坑了!!!主要是题目说得不明确...... 先来看图: 看一下用红圈圈起来的部分,就 ...

  4. LVM备份(3)- pg_dumpall

  5. prometheus 基于文件的目标发现

    prometheus 基于文件的目标发现 1.创建目录 cd /usr/local/prometheus/conf mkdir -pv targets/{nodes,docker} 2.修改prome ...

  6. pip install升级包

    只需要python -m pip install --user --upgrade pip==9.0.3 只需要加一个--user

  7. Pandas系列(三)-缺失值处理

    内容目录 1. 什么是缺失值 2. 丢弃缺失值 3. 填充缺失值 4. 替换缺失值 5. 使用其他对象填充 数据准备 import pandas as pd import numpy as np in ...

  8. 缓存服务—Redis

    Redis 简介Redis 是一个开源(BSD 许可)的.内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 为什么要用 Redis 在高并发场景下,如果需要经常连接结果变动频繁的数据库, ...

  9. 第一次连接数据库mongodb踩的坑

    类型匹配错误,参数要写对了,name与age一一对应. 如果没找到错误就把异常打印出来. await person.save(function(err) { if(err) console.log(e ...

  10. redis发布/订阅

    发布订阅简介 Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息,消息之间通过channel传递. 准备工作 两台安装了redis的机器(虚拟 ...