C# 根据typename字符串,创建任意类型的对象(含泛型)

2024-02-25 20:38

本文主要是介绍C# 根据typename字符串,创建任意类型的对象(含泛型),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

认识一下反射

使用反射得到任意类型

动态创建实例

通过类名获得类型

分析如何获得泛型类型

实现根据类名,获得泛型类型

小计


认识一下反射

在c#中,反射时个很好用的东西,可以通过反射动态创建一个实例,且实例类型不唯一

一个很简单的例子,来了解下反射可以做什么

Type t = typeof(Form);
dynamic frm = t.Assembly.CreateInstance(t.FullName);
// 以上内容完全等同于
dynamic frm = new Form();Type t = typeof(List<string>);
dynamic lst = t.Assembly.CreateInstance(t.FullName);
// 以上内容完全等同于
dynamic lst = new List<string>();

看起来好像反射没什么用,因为他现在完成的,我们都可以自己完成啊

那么,换个场景,有一个函数,传递进来一个object对象,如果对象存在Run方法,就运行该方法,如果不存在Run,但存在Start,则运行Start方法,再不行,就按照Begin、Do等方法依次向后查找,这个时候,如果用switch来枚举object可能的类型不是不可以,但是这样会造成后期需要经常维护此处代码,所以用反射来调用

public void RefInvokeStart(object obj){Type t = obj.GetType();string[] methods = new string[]{"Run","Start","Begin","Do"};for(int i=0;i<methods.Length;i++){MethodInfo method = t.GetMethod(methods[i]);if (method!=null){try{method.Invoke(null,new object[]{obj,null});return;}catch(Exception ex){}}}
}

以上是反射的简单例子,现在翻篇了。

----------------------------------

使用反射得到任意类型

在实际应用中,有时候我们在开发的过程中,脑子会突然抽筋,非常想不开的想用一个方法,来实现不同的需求,嗯,泛型就是为此准备的,但实际工作时,我们只知道对象类型,甚至只知道类型名称,连类型全名(含命名空间路径的类型名称)都不知道,就要创建相应类型的实例

嗯。。。。其实文盲脑子也这么抽过,虽然后来回头看的时候,总觉得不需要这么处理,还有其他方法。。。。但脑子抽的时候可没想过这些 T_T

动态创建实例

先来个根据已知对象动态创建实例的方法

public static T CreateElement<T>(){Type t = typeof(T);return (T)t.Assembly.CreateInstance(t.FullName);
}// 很简单的就可以创建,基本等同于newList<string> ls = CreateElement<List<string>>();

通过类名获得类型

然后,我们只知道类型的名字,不知道全名,也没有确定类型。。。

那么,我们就需要先得到一个Type才可以

        public static Type GetTypeByName(string typename){Type t = null;string source = typename;try{t = Type.GetType(source);if (t != null){return t;}Assembly[] assembly = AppDomain.CurrentDomain.GetAssemblies();foreach (Assembly ass in assembly){t = ass.GetType(source);if (t != null){return t;}Type[] ts = ass.GetTypes();foreach (Type st in ts){if (RegexExpand.IsMatch(st.FullName, @"\." + RegexExpand.FormatRegExp(source) + @"(`?\d+)?$")){return st;}}}}catch (Exception ex){}return t;}

简单来讲,就是根据typename字符串,获得Type类型数据,根据当前项目所调用的所有类库中,查找相同,或者包含我们写的这个名称的类型,并返回,比如 Type t1 = GetTypeByName("string");GetTypeByName("Form");GetTypeByName("Thread");

分析如何获得泛型类型

嗯,简单的名称对照类型就这么简单。再然后,就是重点了,有很多类型是支持泛型的,这些东西能通过反射得到类型吗?

比如,我现在想创建一个 Dictionary<string,Dictionary<int,List<Thread>>>对象,想用 GetTypeByName("Dictionary<string,Dictionary<int,List<Thread>>>")来尝试一下能否获得Type。嗯,不出预料,返回了一个null

因为我们所有对比的内容,都是单一类型,而传递进去的这个字符串,却是一个多类型组合的多泛型结构。。。还tmd带嵌套的

但是,也不是不能实现,整理下思路:

首先,最内层一对<>里肯定不包含其他类型了,这个是已经确定的;

其次,我们肯定不能写一个多泛型的对象,里面多个泛型都还是支持泛型的,比如绝对不会出现Dictionary<List<string>,List<int>>这样的两个泛型都是支持泛型的类型。。有一个就够了

再次,我们根据<>,从里到外获得所有类型字符串,并按顺序记录下来,然后将内层的对象作为参数传递给外层的对象,通过MakeGenericType方法来创建支持泛型的对象

实现根据类名,获得泛型类型

那么,思路有了,接下来就来实现这个方法吧

        public static Type GetTypeByName(string typename){Type t = null;string source = typename;if (source.IndexOf('<') > 0){List<string> lv = new List<string>();while (RegexExpand.IsMatch(source, @"<[^<>]+>")){lv.Add(RegexExpand.Match(source, @"(?<=<)[^<>]+(?=>)").Value);source = RegexExpand.Replace(source, @"<[^<>]+>", "/" + (lv.Count - 1));}List<Type[]> args = new List<Type[]>();for (int i = 0; i < lv.Count; i++){List<Type> arg = new List<Type>();string[] sp = lv[i].Split(',');for (int j = 0; j < sp.Length; j++){string s = sp[j].Trim();if (!string.IsNullOrEmpty(s)){if (RegexExpand.IsMatch(s, @"/\d+$")){Match m = RegexExpand.Match(s, @"^([^/\s]+)\s*/(\d+)$");if (!m.Success){throw new Exception("");}Type p = GetTypeByName(m.Groups[1].Value);Type c = p.MakeGenericType(args[Convert.ToInt32(m.Groups[2].Value)]);arg.Add(c);}else{arg.Add(GetTypeByName(s));}}}args.Add(arg.ToArray());}Match f = RegexExpand.Match(source, @"^([^/\s]+)\s*/(\d+)$");if (!f.Success){throw new Exception("");}Type fp = GetTypeByName(f.Groups[1].Value);Type fc = fp.MakeGenericType(args[Convert.ToInt32(f.Groups[2].Value)]);return fc;}else{try{t = Type.GetType(source);if (t != null){return t;}Assembly[] assembly = AppDomain.CurrentDomain.GetAssemblies();foreach (Assembly ass in assembly){t = ass.GetType(source);if (t != null){return t;}Type[] ts = ass.GetTypes();foreach (Type st in ts){if (RegexExpand.IsMatch(st.FullName, @"\." + RegexExpand.FormatRegExp(source) + @"(`?\d+)?$")){return st;}}}}catch (Exception ex){}}return t;}

得到类型了,创建实例就跟简单了,将之前出现的CreateElement变动一下

public static dynamic CreateElement(string typename){Type t = GetTypeByName(typename);return t.Assembly.CreateInstance(t.FullName);
}

最后就是创建实例对象了

dynamic obj = CreateElement("Dictionary<string,Dictionary<int,List<Thread>>>");

bingo,成了!

-------------

小计

结束语:虽然这个东西确实做出来了,但以我多次脑抽的经验来看,用的上这个方法的人,多半处于脑抽状态

这篇关于C# 根据typename字符串,创建任意类型的对象(含泛型)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/746632

相关文章

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

mybatis-plus如何根据任意字段saveOrUpdateBatch

《mybatis-plus如何根据任意字段saveOrUpdateBatch》MyBatisPlussaveOrUpdateBatch默认按主键判断操作类型,若需按其他唯一字段(如agentId、pe... 目录使用场景方法源码方法改造首先在service层定义接口service层接口实现总结使用场景my

C#下Newtonsoft.Json的具体使用

《C#下Newtonsoft.Json的具体使用》Newtonsoft.Json是一个非常流行的C#JSON序列化和反序列化库,它可以方便地将C#对象转换为JSON格式,或者将JSON数据解析为C#对... 目录安装 Newtonsoft.json基本用法1. 序列化 C# 对象为 JSON2. 反序列化

Python中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

C#文件复制异常:"未能找到文件"的解决方案与预防措施

《C#文件复制异常:未能找到文件的解决方案与预防措施》在C#开发中,文件操作是基础中的基础,但有时最基础的File.Copy()方法也会抛出令人困惑的异常,当targetFilePath设置为D:2... 目录一个看似简单的文件操作问题问题重现与错误分析错误代码示例错误信息根本原因分析全面解决方案1. 确保

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则