zoukankan      html  css  js  c++  java
  • 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()
        {
        }
    }
    View Code

    然后在主函数中加入代码:

    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[1];
    parameters[0] = "test string";
    object obj = assembly.CreateInstance("ReflectionTest.Test",true,System.Reflection.BindingFlags.Default,null,parameters,null,null);// 创建类的实例 
    View Code

    调试结果:正常,并且对象中变量值也是正确的,但是这离笔者的需求还差很远。继续
    第三次测试,继续加深难度,创建string的对象

    首先知道string是System.String的别名,所以要创建的是System.String的对象,而System.String在mscorlib.dll中,所以需要将mscorlib.dll实例为System.Reflection.Assembly的对象,这里利用System.Type类型的属性Assembly来实现功能。

    System.String的构造函数有很多种,本文中笔者就不墨迹了,采用String( Char []) 。

    最终将主函数中代码改为:

    Type type = Type.GetType("System.String");
    object[] parameters = new object[1];
    char[] lpChar = { 't','e','s','t' };
    parameters[0] = lpChar;
    
    object obj = type.Assembly.CreateInstance("ReflectionTest.Test",true,System.Reflection.BindingFlags.Default,null,parameters,null,null);// 创建类的实例 
    View Code

    调试结果:对象为空,失败了,事实上这种方法还有个问题,如将Test类构造函数修改为

    public Test(string str)
    {
        ID = str;//属性赋值
    }
    View Code

    调试结果:对象创建成功,但是变量为空

    以上问题详细原因笔者现在也无法解释,正在查找相关资料。

    解决方案
    最后笔者在《C#中使用反射获取结构体实例及思路》一文中找到了解决方案

    采用System.Activator 类的CreateInstance方法。

    最后见代码:

    Type type = Type.GetType("System.String");
    object[] parameters = new object[1];
    char[] lpCh = { 't', 'e', 's', 't' };
    parameters[0] = lpCh;
    
    object obj = Activator.CreateInstance(type, parameters);
    View Code

    调试结果:对象创建成功,且变量值正常

    结论

    采用System.Activator 类的CreateInstance方法,要比System.Reflection.Assembly的CreateInstance简单有效很多。有兴趣的朋友可以仔细看看。详细资料http://msdn.microsoft.com/zh-cn/library/system.activator(v=vs.110).aspx

  • 相关阅读:
    关于Maya Viewport 2.0 API 开发的介绍视频
    春节大假
    Some tips about the life cycle of Maya thread pool
    Can I compile and run Dx11Shader for Maya 2015 on my side?
    How to get current deformed vertex positions in MoBu?
    想加入全球首届的 欧特克云加速计划吗?
    三本毕业(非科班),四次阿里巴巴面试,终拿 offer(大厂面经)
    mac、window版编辑器 webstorm 2016... 永久破解方法。
    node 搭载本地代理,处理web本地开发跨域问题
    js 一维数组,转成嵌套数组
  • 原文地址:https://www.cnblogs.com/max198727/p/3431907.html
Copyright © 2011-2022 走看看