使用C#反射中的MAKEGENERICTYPE函数,来为泛型方法和泛型类指定(泛型的)类型
MakeGenericType 是一个在 C# 中用于创建开放类型的实例的方法。开放类型是一种未绑定类型参数的泛型类型。当你有一个泛型类型定义,并且想要用特定的类型实例化它时,你可以使用 MakeGenericType 方法。
public Type MakeGenericType (params Type[] typeArguments);
这个方法接受一个 Type[] 作为参数,其中包含了用来替换泛型类型定义中的类型参数的类型。
例如,假设你有一个泛型类 Pair<T, U>,你想要创建一个 Pair<int, string> 的实例。你可以这样做:
// 泛型类型定义
public class Pair<T, U> {public T First { get; set; }public U Second { get; set; }
}// 创建泛型类型的实例
Type pairType = typeof(Pair<,>); // 获取开放类型
Type[] typeArguments = { typeof(int), typeof(string) }; // 实例化类型参数
Type pairInstanceType = pairType.MakeGenericType(typeArguments); // 创建实例类型// 创建实例
object pairInstance = Activator.CreateInstance(pairInstanceType);
在这个例子中,pairType 是一个开放类型,typeArguments 是用来替换 T 和 U 的具体类型。pairInstanceType 是一个已经绑定了具体类型参数的 Pair<int, string> 类型。最后,我们使用 Activator.CreateInstance 来创建这个类型的实例。
C#反射中的MakeGenericType函数可以用来指定泛型方法和泛型类的具体类型,方法如下面代码所示这里就不多讲了,详情看下面代码一切就清楚了:
using System;
using System.Reflection;namespace RFTest
{//类ReflectionTest中定义了一个泛型函数DisplayType和泛型类MyGenericClassclass ReflectionTest{//泛型类MyGenericClass有个静态函数DisplayNestedTypepublic class MyGenericClass<T>{public static void DisplayNestedType(){Console.WriteLine(typeof(T).ToString());}}public void DisplayType<T>(){Console.WriteLine(typeof(T).ToString());}}class Program{static void Main(string[] args){ReflectionTest rt = new ReflectionTest();MethodInfo mi = rt.GetType().GetMethod("DisplayType");//先获取到DisplayType<T>的MethodInfo反射对象mi.MakeGenericMethod(new Type[] { typeof(string) }).Invoke(rt, null);//然后使用MethodInfo反射对象调用ReflectionTest类的DisplayType<T>方法,这时要使用MethodInfo的MakeGenericMethod函数指定函数DisplayType<T>的泛型类型TType myGenericClassType = rt.GetType().GetNestedType("MyGenericClass`1");//这里获取MyGenericClass<T>的Type对象,注意GetNestedType方法的参数要用MyGenericClass`1这种格式才能获得MyGenericClass<T>的Type对象myGenericClassType.MakeGenericType(new Type[] { typeof(float) }).GetMethod("DisplayNestedType", BindingFlags.Static | BindingFlags.Public).Invoke(null, null);//然后用Type对象的MakeGenericType函数为泛型类MyGenericClass<T>指定泛型T的类型,比如上面我们就用MakeGenericType函数将MyGenericClass<T>指定为了MyGenericClass<float>,然后继续用反射调用MyGenericClass<T>的DisplayNestedType静态方法Console.ReadLine();}}
}
C# 反射
反射是一种在运行时动态获取程序类型信息的技术,它可以用来查找和操作程序中的类型、成员、属性和方法等。
(1)获取Type类型的几种方法:
(a) 实例调用GetType
(b) typeof(类型)
(c) Assembly.GetType(类型名称)
(d) Type.GetType(类型全称)
(2)获取数组类型
typeof(类型).MakeArrayType()
如typeof(int).MakeArrayType()==typeof(int[]) //为true
(3)根据数组类型返回元素类型typeof(int[]).GetElementType()==typeof(int)//为true
(4)类型具有Namespace,Name,FullName属性,FullName基本等于前两者组合在一起。
(5)数组,指针,ref,out 参数类型名称
MakeGenericType的使用:
MakeGenericType 方法用于创建一个泛型类型的实例,其中可以通过传递类型参数来指定具体的泛型参数类型。这在需要在运行时动态创建泛型类型的情况下非常有用。下面是一个示例代码演示如何使用 MakeGenericType 方法:
假设有一个泛型类 MyGenericClass,你想要在运行时为其指定具体的类型参数并创建实例。首先,定义泛型类如下:
using System;public class MyGenericClass<T>
{public void PrintType(){Console.WriteLine(typeof(T).Name);}
}
接下来,可以使用 MakeGenericType 方法来动态创建泛型类型的实例:
using System;class Program
{static void Main(string[] args){// 获取泛型类型的定义Type genericTypeDefinition = typeof(MyGenericClass<>);// 指定泛型类型参数Type[] typeArguments = { typeof(int) };// 使用MakeGenericType创建泛型类型实例Type specificType = genericTypeDefinition.MakeGenericType(typeArguments);object instance = Activator.CreateInstance(specificType);// 调用泛型类型的方法var printMethod = specificType.GetMethod("PrintType");printMethod.Invoke(instance, null);}
}
在这个示例中,首先获取了泛型类型的定义 MyGenericClass<>,然后指定了具体的泛型类型参数,例如 int。接着使用 MakeGenericType 创建了指定参数的泛型类型实例,并通过 Activator.CreateInstance 创建了实例对象。最后,使用反射调用了泛型类型的方法。
using System;
using System.Reflection;class Program
{static void Main(string[] args){// 通过反射查找类型Type type = Type.GetType("Demo.Person");// 通过反射创建对象object person = Activator.CreateInstance(type);// 通过反射调用方法MethodInfo methodInfo = type.GetMethod("SayHello");methodInfo.Invoke(person, null);// 通过反射获取属性PropertyInfo propertyInfo = type.GetProperty("Name");Console.WriteLine("Name: {0}", propertyInfo.GetValue(person));// 通过反射修改属性propertyInfo.SetValue(person, "Tom", null);Console.WriteLine("Name: {0}", propertyInfo.GetValue(person));// 通过反射获取字段FieldInfo fieldInfo = type.GetField("Age");Console.WriteLine("Age: {0}", fieldInfo.GetValue(person));// 通过反射修改字段fieldInfo.SetValue(person, 20);Console.WriteLine("Age: {0}", fieldInfo.GetValue(person));}
}class Person
{public string Name { get; set; }public int Age;public void SayHello(){Console.WriteLine("Hello, my name is {0}.", Name);}
}
在这个示例中,我们通过反射查找了一个名为Demo.Person的类型,并创建了一个该类型的对象。然后,我们使用反射获取了该对象的SayHello方法,并通过Invoke方法调用了该方法。接着,我们使用反射获取了该对象的Name属性,并获取了该属性的值。然后,我们通过反射修改了该对象的Name属性的值,并再次获取了该属性的值。最后,我们使用反射获取了该对象的Age字段,并获取了该字段的值。然后,我们通过反射修改了该对象的Age字段的值,并再次获取了该字段的值。
·使用反射调用构造器,可以通过以下步骤实现:
通过Type.GetType方法或者typeof关键字获取目标类型的Type对象。例如,获取Demo.Person类型的Type对象可以使用以下代码:Type type = Type.GetType("Demo.Person"); 或者 Type type = typeof(Demo.Person);
Activator.CreateInstance和constructor.Invoke都可以用于创建对象,但它们的实现方式有所不同。
Activator.CreateInstance是一个静态方法,它使用指定的类型名、程序集名、参数等信息来创建一个实例。它可以自动选择适当的构造函数进行创建,并且支持泛型类型的创建。使用Activator.CreateInstance可以避免手动获取构造函数的过程,让创建对象的过程更加简便。但是,由于其通过字符串来指定类型名和程序集名,因此需要在编译时指定完整的类型名和程序集名,不太方便动态获取类型。
constructor.Invoke则是使用反射获取到一个构造函数后,通过Invoke方法来调用构造函数,创建一个对象。与Activator.CreateInstance相比,使用constructor.Invoke需要手动获取构造函数,需要明确指定构造函数的参数,因此相对来说更加复杂。但是,它可以在运行时动态获取类型和构造函数,更加灵活。
总的来说,Activator.CreateInstance适用于已知类型名和程序集名的情况,可以让创建对象更加简便;而constructor.Invoke适用于需要动态获取类型和构造函数的情况,更加灵活。
相关文章:
使用C#反射中的MAKEGENERICTYPE函数,来为泛型方法和泛型类指定(泛型的)类型
MakeGenericType 是一个在 C# 中用于创建开放类型的实例的方法。开放类型是一种未绑定类型参数的泛型类型。当你有一个泛型类型定义,并且想要用特定的类型实例化它时,你可以使用 MakeGenericType 方法。 public Type MakeGenericType (params Type[] ty…...
sql注入 (运用sqlmap解题)
注:level参数 使用–batch参数可指定payload测试复杂等级。共有五个级别,从1-5,默认值为1。等级越高,测试的payload越复杂,当使用默认等级注入不出来时,可以尝试使用–level来提高测试等级。 --level 参数决定了 sql…...
HTML5 Canvas 绘图教程二
在本教程中,我们将探讨 canvas 的高级用法,包括复杂的绘图 API、坐标系统和变换操作、平滑动画技术以及复杂应用和游戏开发的实践。 1. 绘图 API 高级方法 1.1 二次贝塞尔曲线 (quadraticCurveTo) 二次贝塞尔曲线需要两个点:一个控制点和一…...
Linux 命令 find 的深度解析与使用
Linux 命令 find 的深度解析与使用 在 Linux 系统中,find 命令是一个功能强大的工具,用于在文件系统中搜索文件或目录。无论是基于文件名、文件类型、文件大小、文件权限,还是基于文件的最后修改时间等,find 命令都能提供灵活的搜…...
字符串操作记录
1 拼接 Concat():拼接字符串 Let stringvalue “hello ”; Let result stringvalue.concat(“world”) Console.log(result) // “hello world” 2 删 Let stringvalue “hello world”Console.log(stringvalue.slice(3)); // ‘lo world’Console.log(stringvalue.subst…...
【python科学文献计量】关于中国知网检索策略的验证,以事故伤害严重程度检索为例
关于中国知网检索策略的验证,以事故伤害严重程度检索为例 1 背景2 文献下载3 数据处理1 背景 由于要进行相关研究内容的综述,需要了解当前我国对于事故伤害严重程度的研究现状,采用国内较为知名的检索网站(中国知网)进行文献数据集检索 由于最近知网出bug,检索的结果在…...
AdminController
目录 1、 AdminController 1.1、 UpdateFaculty 1.1.1、 // Check if a new image file is provided 1.1.2、 // CHECKING FOLDER EXIST OR NOT - IF NOT THEN CREATE F0LDER 1.1.3、 // READY SEND PATH TO IMAGE TO DB 1.1.4、 DeleteFaculty 1.1.5、 // If th…...
Vue3-Pinia状态管理器
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。如果你熟悉组合式 API 的话,你可能会认为可以通过一行简单的 export const state reactive({}) 来共享一个全局状态。对于单页应用来说确实可以,但如果应用在服务器端渲染&…...
安装存储器的段描述符并加载GDTR
代码清单 ;代码清单12-1;文件名:c12_mbr.asm;文件说明:硬盘主引导扇区代码;创建日期:2011-5-16 19:54;修改于2022-02-16 11:15;设置堆栈段和栈指针mov ax, csmov ss, axmov sp, 0x7c00;计算GDT所在的逻辑段地址12 mov ax, [c…...
2024年5月架构试题
2024年5月份架构师考试真题完整版 截至2024-5-28 19:24:14已全部收录完成 共75道选择题,5道案例题,4道论文题。题目顺序不分先后。 全网最全的2024年5月份架构师考试真题回忆版,包含答案和解析。 选择题 计算机基础 操作系统调度算法 选先来先…...
品牌控价的同时也要做好数据分析
品牌在进行电商价格监测时,确实不应仅停留在收集低价数据的层面。在数据量巨大的今天,如何深度分析和挖掘这些数据的价值,为品牌的决策和战略提供有力支持,显得尤为重要。 首先,电商数据的监测和分析有助于品牌更全面…...
微服务学习Day11-缓存问题学习
文章目录 多级缓存引入JVM进程缓存导入商品案例Caffeine学习实现进程缓存 Lua语法入门认识Lua变量和循环条件控制、函数 多级缓存安装OpenRestyOpenResty入门请求参数处理查询TomcatRedis缓存预热查询Redis缓存Nginx本地缓存 缓存同步策略策略安装Canal监听Canal 多级缓存引入 …...
虚拟化知识学习
虚拟化知识学习 关键概念和术语的简要介绍 虚拟化的基本概念 虚拟机 (VM):一个虚拟机是一个模拟计算机系统的环境。它运行在物理硬件之上,但与物理硬件隔离,提供类似于物理计算机的功能。 虚拟化技术:这是指使用软件来创建虚拟版…...
一键生成迷宫-Word插件-大珩助手新功能
Word大珩助手是一款功能丰富的Office Word插件,旨在提高用户在处理文档时的效率。它具有多种实用的功能,能够帮助用户轻松修改、优化和管理Word文件,从而打造出专业而精美的文档。 【新功能】迷宫生成器 1、可自定义迷宫大小; …...
运维开发详解(上)
🐇明明跟你说过:个人主页 🏅个人专栏:《Linux :从菜鸟到飞鸟的逆袭》🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是运维开发 二、运维开发的基础知识 1、运…...
react useState基本使用
1. React Hooks介绍 React Hooks是React 16.8版本引入的新特性,它允许在不编写类的情况下使用state和其他React特性。Hooks的引入极大地简化了组件的编写,使得函数式组件能够拥有类似类组件的功能。 1.1 函数式组件与类组件的区别 函数式组件与类组件…...
基于jeecgboot-vue3的Flowable流程-待办任务(二)
因为这个项目license问题无法开源,更多技术支持与服务请加入我的知识星球。 接下来讲待办的流程处理 1、根据这个vue3新的框架,按钮代码如下: /*** 操作栏*/function getTableAction(record) {return [{label: 处理,onClick: handleProcess…...
1103. 分糖果 II
1103. 分糖果 II 题目链接:1103. 分糖果 II 代码如下: class Solution { public:vector<int> distributeCandies(int candies, int num_people) {vector<int> res(num_people,0);int count1,i0;//count代表此时对应第i个人需要分得糖果wh…...
SQL实验 数据的插入、修改和删除操作
一、实验目的 1.掌握Management Studio的使用。 2.掌握SQL中INSERT、UPDATE、DELETE命令的使用。 二、实验内容及要求 用SQL语句完成下列功能。使用数据库为SCHOOL数据库。 1、新开设一门课程,名叫网络安全与防火墙,学时40&#x…...
es初始化
一.初始化es public void initES() {/*LOGGER.info("host" host);LOGGER.info("port" port);LOGGER.info("scheme" scheme);LOGGER.info("userName" userName);LOGGER.info("password" password);*/// 客户端连接创建…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
