C#利用反射动态创建对象 带参数的构造函数和String类型 (转载)
最近笔者有一个想法需要利用反射动态创建对象(如string,int,float,bool,以及自定义类等)来实现,一直感觉反射用不好,特别是当构造函数带参数的时候。
MSDN上给出的例子十分复杂,网上的帖子则一般都说很简单,那就看看网上比较普遍的说法:
“反射”其实就是利用程序集的元数据信息。 反射可以有很多方法,编写程序时请先导入 System.Reflection 命名空间,假设你要反射一个 DLL 中的类,并且没有引用它(即未知的类型):
Assembly assembly = Assembly.LoadFile("程序集路径,不能是相对路径"); // 加载程序集(EXE 或 DLL)
object obj = assembly.CreateInstance("类的完全限定名(即包括命名空间)"); // 创建类的实例 若要反射当前项目中的类可以为: Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集
object obj = assembly.CreateInstance("类的完全限定名(即包括命名空间)"); // 创建类的实例,返回为 object 类型,需要强制类型转换 也可以为:
Type type = Type.GetType("类的完全限定名");
object obj = type.Assembly.CreateInstance(type); 反射创建类的实例
因为这段描述在很多地方都有看到,笔者也不知道原始出处,所以这里就给出笔者第一次看到的地方:http://hi.baidu.com/rayord/item/92e58ddb0d34c13de3108fbb
上述描述中提到的三种方法其实都是大同小异的,核心就是通过System.Reflection..::.Assembly 类型的CreateInstance方法创建实例。
关于System.Reflection..::.Assembly 类可以直接在MSDN上查询详细信息http://msdn.microsoft.com/zh-cn/library/system.reflection.assembly(v=vs.110).aspx
那么简单的解释一下这种方法的原理:
1.找到要实例化的类所在的程序集,并将之实例为System.Reflection..::.Assembly 类的对象
2.利用System.Reflection..::.Assembly 类提供的CreateInstance方法,创建类的对象
看起来确实很简单,只是这种方法真的好用么?
笔者进行了测试以说明:
第一次测试,创建一个简单的自定义类型对象
首先创建一个类:
class Test
{
private string _strId;
public string ID
{
get { return _strId; }
set { _strId = value; }
} public Test()
{
}
}
然后在主函数中加入代码:
Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集 object obj = assembly.CreateInstance("ReflectionTest.Test"); //类的完全限定名(即包括命名空间)
调试结果:显示obj对象的确不为空,证明这种方法可行。
第二次测试,加深难度,测试类的构造函数需要传递参数
首先修改Test类,将其构造函数改为:
public Test(string str)
{
_strId = str;
}
调试结果:直接抛出异常:未找到类型“ReflectionTest.Test”上的构造函数。这是因为CreateInstance方法默认情况下是通过找无参数的构造函数去创建对象的,现在找不到当然会出错,实时上CreateInstance方法提供了3中签名,其中有CreateInstance(String, Boolean, BindingFlags, Binder, Object [], CultureInfo, Object []) 就可以满足这种情况:
修改主函数如下:
Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集
//object obj = assembly.CreateInstance("ReflectionTest.Test"); //类的完全限定名(即包括命名空间)
object[] parameters = new object[];
parameters[] = "test string";
object obj = assembly.CreateInstance("ReflectionTest.Test",true,System.Reflection.BindingFlags.Default,null,parameters,null,null);// 创建类的实例
调试结果:正常,并且对象中变量值也是正确的,但是这离笔者的需求还差很远。继续
第三次测试,继续加深难度,创建string的对象
首先知道string是System.String的别名,所以要创建的是System.String的对象,而System.String在mscorlib.dll中,所以需要将mscorlib.dll实例为System.Reflection..::.Assembly的对象,这里利用System.Type类型的属性Assembly来实现功能。
System.String的构造函数有很多种,本文中笔者就不墨迹了,采用String( array<Char []()>[]) 。
最终将主函数中代码改为:
Type type = Type.GetType("System.String");
object[] parameters = new object[];
char[] lpChar = { 't','e','s','t' };
parameters[] = lpChar;
object obj = type.Assembly.CreateInstance("ReflectionTest.Test",true,System.Reflection.BindingFlags.Default,null,parameters,null,null);// 创建类的实例
调试结果:对象为空,失败了,事实上这种方法还有个问题,如将Test类构造函数修改为
public Test(string str)
{
ID = str;//属性赋值
}
调试结果:对象创建成功,但是变量为空
以上问题详细原因笔者现在也无法解释,正在查找相关资料。
解决方案
采用System.Activator 类的CreateInstance方法。
最后见代码:
Type type = Type.GetType("System.String");
object[] parameters = new object[];
char[] lpCh = { 't', 'e', 's', 't' };
parameters[] = lpCh;
object obj = Activator.CreateInstance(type, parameters);
调试结果:对象创建成功,且变量值正常
结论
采用System.Activator 类的CreateInstance方法,要比System.Reflection.Assembly的CreateInstance简单有效很多。有兴趣的朋友可以仔细看看。
补充知识点
使用Type.GetType(string typeName)方法获取类型时,参数typeName中声明的程序集没有必要在当前项目中引用,只要放在生成项目的bin目录下即可:
比如下面我构造了一个类库项目MyClass包含类MyClassObject
public class MyClassObject
{
}

我在项目ConsoleApplication2中并没有引用类库项目MyClass的程序集,如下图所示

但是我手动将类库项目MyClass的DLL文件复制到了项目ConsoleApplication2的bin目录下:

然后我在项目ConsoleApplication2中使用:
Type myType = Type.GetType("MyClass.MyClassObject,MyClass");
是可以成功获取到MyClassObject的Type类型的:

这说明C#中使用反射,在项目中不引用程序集也可以构造程序集中的类,只要将程序集文件(DLL文件)放在和项目所生成文件相同的文件夹(一般是bin目录)下即可。
C#利用反射动态创建对象 带参数的构造函数和String类型 (转载)的更多相关文章
- C# 利用反射动态创建对象——带参数的构造函数和String类型
C# 利用反射动态创建对象——带参数的构造函数和String类型 最近笔者有一个想法需要利用反射动态创建对象(如string,int,float,bool,以及自定义类等)来实现,一直感觉反射用不好, ...
- C# 利用反射动态创建对象[摘录]
摘自:http://hi.baidu.com/yangyuhang/blog/item/f12ea90e13f214e336d12250.html 在VS.Net中,有很多种方法动态调用对象的构造函数 ...
- 【转】C# 利用反射动态创建对象
http://www.cnblogs.com/Jan_Dai/archive/2010/11/09/1872812.html Activator.CreateInstance(Type.GetType ...
- C#回顾 - 8.利用反射动态创建对象
拿微信消息返回的示例数据实验 var data = "<xml><ToUserName><![CDATA[toUser]]></ToUserName ...
- C# 利用反射动态加载dll
笔者遇到的一个问题,dll文件在客户端可以加载成功,在web端引用程序报错.解决方法:利用反射动态加载dll 头部引用加: using System.Reflection; 主要代码: Assembl ...
- C# 知识点笔记:IEnumerable<>的使用,利用反射动态调用方法
IEnumerable<T>的使用 创建一个IEnumerable对象 List<string> fruits = new List<string> { " ...
- .Net Core利用反射动态加载类库的方法(解决类库不包含Nuget依赖包的问题)
在.Net Framework时代,生成类库只需将类库项目编译好,然后拷贝到其他项目,即可引用或动态加载,相对来说,比较简单.但到了.Net Core时代,动态加载第三方类库,则稍微麻烦一些. 一.类 ...
- C#的泛型的类型参数可以有带参数的构造函数的约束方式吗?
Review后看到标题让我十分羞愧自己语文功底太差,估计...请见谅......我还特地把这句写回开头了...... 问题 前天遇到的一个问题,所以在MSDN发了个问,刚也丰富了下问题,关于泛型的. ...
- mfc 带参数的构造函数
知识点 默认的构造函数 带参数的构造函数 重载构造函数 一.默认的构造函数 二.带参数的构造函数 三.重载构造函数 class Tdate { public: int year;//年 int mon ...
随机推荐
- SqlServer 2005升级至SqlServer 2008 解析Json 字符集问题
如果你数据库是通过sqlserver 2008以上版本创建的请绕过: 客户以前用的是sqlserver2005 创建的数据库.后来升级到 sqlserver 2008 . 有个业务用到了json查询 ...
- SQLServer数据库系统概念
数据模型是一种抽象模型,现实世界中的客观事物是彼此相互联系的 (1)数据模型是一组集成的概念,用户描述和操作组织内的数据,数据间的联系以及对数据的约束,它包含了数据结构,数据操作和完整性约束 (2)概 ...
- BZOJ5372: PKUSC2018神仙的游戏
传送门 Sol 自己还是太 \(naive\) 了,上来就构造多项式和通配符直接匹配,然后遇到 \(border\) 相交的时候就 \(gg\) 了 神仙的游戏蒟蒻还是玩不来 一个小小的性质: 存在长 ...
- 转:Linux中tomcat服务成功发布但局域网浏览器无法访问
转自:http://blog.csdn.net/mooncom/article/details/53168143 昨天,我在搭建Linux中服务器环境时,碰见一个问题,这里和大家分享一下. 问题描述: ...
- Google Protocol Buffer 的使用(未完待续)
简介 Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 ...
- 辅助判卷程序的一些小bug
首先谈一下,double类型 之前查过一些资料,double类型做==(相等)判断时候,会出现一些错误,及61.95与61.95不相等 对main函数中的部分加以改正,下面的answer为string ...
- Week2——提交表单后后台的工作
在我理解看来,发生请求后主要是通过域进行相互间的协调作用的.表单数据可以从request域中获得,也可以通过response域返回数据给前台. 当发起http请求后,已经启动的Tomcat服务器解析收 ...
- 我的MBTI小测试
今天做了自己的MBTI测试,选了93道题版本的,测试结果是ESFP表演者型——有我在就有笑声.这个测试很有趣,我也觉得很神奇. 一.我的MBTI图形 二.才储分析:我的性格类型倾向为“ ESFP ”( ...
- 【Yii系列】Yii2.0的安装与调试
接上一节的话,我们最终选择了Yii框架作为我们的主要开发框架,今天,我就和大伙来聊聊如何安装与调试Yii2.0,以及后续会和大伙聊聊如何在Yii2.0上快速撸代码. Yii2.0的安装 好的,Comp ...
- 京东原来你运用的这玩意,不错,我也要!! ContainerDNS
转自社区 ContainerDNS 本文介绍的 DNS 命名为 ContainerDNS,作为京东商城软件定义数据中心的关键基础服务之一,具有以下特点: 分布式,高可用 自动发现服务域名 后端探活 易 ...