使用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 ...
随机推荐
- Vim简明学习
前面的话 在linux云服务器上的编辑器默认是vim,类似于windows系统中的记事本,页面简洁,但入门不易.本文将介绍Vim的基础使用 操作模式 vim编辑器有三种模式: 1.命令模式(等待用户输 ...
- Flask的插件session、SQLAlchemy、Script、Migrate
一.flask-session 1.为什么要使用flask-session 因为flask默认的session是通过请求上下文放入到Local中的,是存在内存的,而使用flask-session可以更 ...
- P1033 自由落体
原题链接 https://www.luogu.org/problemnew/show/P1033 不得不说,这个题太坑了!!!主要是题目说得不明确...... 先来看图: 看一下用红圈圈起来的部分,就 ...
- LVM备份(3)- pg_dumpall
- prometheus 基于文件的目标发现
prometheus 基于文件的目标发现 1.创建目录 cd /usr/local/prometheus/conf mkdir -pv targets/{nodes,docker} 2.修改prome ...
- pip install升级包
只需要python -m pip install --user --upgrade pip==9.0.3 只需要加一个--user
- Pandas系列(三)-缺失值处理
内容目录 1. 什么是缺失值 2. 丢弃缺失值 3. 填充缺失值 4. 替换缺失值 5. 使用其他对象填充 数据准备 import pandas as pd import numpy as np in ...
- 缓存服务—Redis
Redis 简介Redis 是一个开源(BSD 许可)的.内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 为什么要用 Redis 在高并发场景下,如果需要经常连接结果变动频繁的数据库, ...
- 第一次连接数据库mongodb踩的坑
类型匹配错误,参数要写对了,name与age一一对应. 如果没找到错误就把异常打印出来. await person.save(function(err) { if(err) console.log(e ...
- redis发布/订阅
发布订阅简介 Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息,消息之间通过channel传递. 准备工作 两台安装了redis的机器(虚拟 ...