当前位置: 首页 > news >正文

使用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# 中用于创建开放类型的实例的方法。开放类型是一种未绑定类型参数的泛型类型。当你有一个泛型类型定义&#xff0c;并且想要用特定的类型实例化它时&#xff0c;你可以使用 MakeGenericType 方法。 public Type MakeGenericType (params Type[] ty…...

sql注入 (运用sqlmap解题)

注:level参数 使用–batch参数可指定payload测试复杂等级。共有五个级别&#xff0c;从1-5&#xff0c;默认值为1。等级越高&#xff0c;测试的payload越复杂&#xff0c;当使用默认等级注入不出来时&#xff0c;可以尝试使用–level来提高测试等级。 --level 参数决定了 sql…...

HTML5 Canvas 绘图教程二

在本教程中&#xff0c;我们将探讨 canvas 的高级用法&#xff0c;包括复杂的绘图 API、坐标系统和变换操作、平滑动画技术以及复杂应用和游戏开发的实践。 1. 绘图 API 高级方法 1.1 二次贝塞尔曲线 (quadraticCurveTo) 二次贝塞尔曲线需要两个点&#xff1a;一个控制点和一…...

Linux 命令 find 的深度解析与使用

Linux 命令 find 的深度解析与使用 在 Linux 系统中&#xff0c;find 命令是一个功能强大的工具&#xff0c;用于在文件系统中搜索文件或目录。无论是基于文件名、文件类型、文件大小、文件权限&#xff0c;还是基于文件的最后修改时间等&#xff0c;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 的专属状态管理库&#xff0c;它允许你跨组件或页面共享状态。如果你熟悉组合式 API 的话&#xff0c;你可能会认为可以通过一行简单的 export const state reactive({}) 来共享一个全局状态。对于单页应用来说确实可以&#xff0c;但如果应用在服务器端渲染&…...

安装存储器的段描述符并加载GDTR

代码清单 ;代码清单12-1;文件名&#xff1a;c12_mbr.asm;文件说明&#xff1a;硬盘主引导扇区代码;创建日期&#xff1a;2011-5-16 19:54&#xff1b;修改于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道选择题&#xff0c;5道案例题&#xff0c;4道论文题。题目顺序不分先后。 全网最全的2024年5月份架构师考试真题回忆版&#xff0c;包含答案和解析。 选择题 计算机基础 操作系统调度算法 选先来先…...

品牌控价的同时也要做好数据分析

品牌在进行电商价格监测时&#xff0c;确实不应仅停留在收集低价数据的层面。在数据量巨大的今天&#xff0c;如何深度分析和挖掘这些数据的价值&#xff0c;为品牌的决策和战略提供有力支持&#xff0c;显得尤为重要。 首先&#xff0c;电商数据的监测和分析有助于品牌更全面…...

微服务学习Day11-缓存问题学习

文章目录 多级缓存引入JVM进程缓存导入商品案例Caffeine学习实现进程缓存 Lua语法入门认识Lua变量和循环条件控制、函数 多级缓存安装OpenRestyOpenResty入门请求参数处理查询TomcatRedis缓存预热查询Redis缓存Nginx本地缓存 缓存同步策略策略安装Canal监听Canal 多级缓存引入 …...

虚拟化知识学习

虚拟化知识学习 关键概念和术语的简要介绍 虚拟化的基本概念 虚拟机 (VM)&#xff1a;一个虚拟机是一个模拟计算机系统的环境。它运行在物理硬件之上&#xff0c;但与物理硬件隔离&#xff0c;提供类似于物理计算机的功能。 虚拟化技术&#xff1a;这是指使用软件来创建虚拟版…...

一键生成迷宫-Word插件-大珩助手新功能

Word大珩助手是一款功能丰富的Office Word插件&#xff0c;旨在提高用户在处理文档时的效率。它具有多种实用的功能&#xff0c;能够帮助用户轻松修改、优化和管理Word文件&#xff0c;从而打造出专业而精美的文档。 【新功能】迷宫生成器 1、可自定义迷宫大小&#xff1b; …...

运维开发详解(上)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、什么是运维开发 二、运维开发的基础知识 1、运…...

react useState基本使用

1. React Hooks介绍 React Hooks是React 16.8版本引入的新特性&#xff0c;它允许在不编写类的情况下使用state和其他React特性。Hooks的引入极大地简化了组件的编写&#xff0c;使得函数式组件能够拥有类似类组件的功能。 1.1 函数式组件与类组件的区别 函数式组件与类组件…...

基于jeecgboot-vue3的Flowable流程-待办任务(二)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 接下来讲待办的流程处理 1、根据这个vue3新的框架&#xff0c;按钮代码如下&#xff1a; /*** 操作栏*/function getTableAction(record) {return [{label: 处理,onClick: handleProcess…...

1103. 分糖果 II

1103. 分糖果 II 题目链接&#xff1a;1103. 分糖果 II 代码如下&#xff1a; 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&#xff0e;掌握Management Studio的使用。 2&#xff0e;掌握SQL中INSERT、UPDATE、DELETE命令的使用。 二、实验内容及要求 用SQL语句完成下列功能。使用数据库为SCHOOL数据库。 1、新开设一门课程&#xff0c;名叫网络安全与防火墙&#xff0c;学时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);*/// 客户端连接创建…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...