反射之动态创建对象

前言

C#有关反射的话题已经是个老生常谈的话题,也许园友一看这标题都不屑去看了,但是既然拿出来讲必有讲之道理,当然,不喜勿喷,高手请绕道!直入话题。

讨论

定义一个Person类代码如下

 1    public class Person
 2     {
 3
 4         /// <summary>
 5         /// 年龄
 6         /// </summary>
 7         public int Age { get; set; }
 8
 9         /// <summary>
10         /// 姓名
11         /// </summary>
12         public string Name { get; set; }
13
14         /// <summary>
15         /// 性别
16         /// </summary>
17         public bool Gender { get; set; }
18
19
20         /// <summary>
21         /// 求两个数的和
22         /// </summary>
23         /// <param name="num1"></param>
24         /// <param name="num2"></param>
25         /// <returns></returns>
26         public int Add(int num1,int num2)
27         {
28             return num1 + num2;
29         }
30     }

那么现在怎么动态获取该对象并打印该对象?啊,用反射动态获取呗,ok,实现如下!

1             Type person = typeof(Person);
2
3             Person t = (Person)Activator.CreateInstance(person) as Person;
4
5             Console.WriteLine(t.ToString());

完全没错,在黑框框中运行输出入下:

接下来小小改动一下,在Person类中添加一个构造函数

1         public Person(string age, string name, bool gender)
2         {
3             this.Age = age;
4             this.Name = name;
5             this.Gender = gender;
6         }

此时我们再来运行看看!!什么鬼,怎么出现错误了???

吓我一跳,平常来个未将对象设置到对象的实例那是见怪不怪了,出现这个容我想想,无参构造函数似乎暗示着什么,突然醒悟对象不都默认有个无参的构造函数吗,啊,shit,原来是因为我定义了一个有参数的构造函数,用Activator.CreateInstance动态创建对象调用的无参构造函数啊,紧接着我将鼠标放在该方法跟前,都告诉我了写着 使用指定类型的默认构造函数来创建该类型的实例 ,知道错误所在了,关键是怎么去解决,要是类中写了有参数的构造函数,现在想要反射来动态创建对象岂不是不能够了吗?继续想,记得在javascript中虽然不能够像C#实现重载,当然js也不存在重载,但是可以根据arguments.length来近似于实现所谓的重载,这里同样可不可以根据构造函数的个数来实现呢?有了这个想法就开干,当看到这个GetConstructors方法心底就舒坦起来了,经过反复查看其方法改造控制台后的代码如下:

1             var length = 0;
2             Person p = null;
3             Type person = typeof(Person);
4             var gc = person.GetConstructors();
5             foreach (var c in gc)
6             {
7                 length = c.GetParameters().Length;
8             }

现在获取到了构造函数的长度即可以根据参数的个数来进行创建对象,离解决问题更进一步了,这时我想到如果我参数个数相同,怎么知道我是调用哪个构造函数呢?对,根据参数的类型,所以现在问题上升到怎么确定我要传递参数的类型呢?看看构造函数的属性  ConstructorInfo 中有没有什么方法可以定义参数类型,皇天不负有心人 GetConstructor 方法参数中 有个Type 这就是参数的类型了,然后利用 Invoke 委托对构造函数传入参数获取对象,如下:

 1             ConstructorInfo Constructor = null;
 2
 3             switch (length)
 4             {
 5                 case 0:
 6                     Constructor = person.GetConstructor(new Type[0]);
 7                     p = Constructor.Invoke(null) as Person;
 8                     break;
 9                 case 1:
10                     Constructor = person.GetConstructor(new Type[1] { typeof(int) });
11                     p = Constructor.Invoke(new object[1] { 1 }) as Person;
12                     break;
13                 case 2:
14                     Constructor = person.GetConstructor(new Type[2] { typeof(int), typeof(string) });
15                     p = Constructor.Invoke(new object[2] { 1, "嘿嘿" }) as Person;
16                     break;
17                 case 3:
18                     Constructor = person.GetConstructor(new Type[3] { typeof(int), typeof(string), typeof(bool) });
19                     p = Constructor.Invoke(new object[3] { 1, "嘿嘿", false }) as Person;
20                     break;
21                 default:
22                     break;
23             }
24
25             //Person t = (Person)Activator.CreateInstance(person) as Person;
26             Console.WriteLine(p.ToString());

同样得到上述结果打印出:反射之动态创建对象.Person,ok,终于解决了,完美!

拓展

在上述过程中用到委托Invoke再传入参数到其中,鉴于此对于反射,参考代码改善建议利用dynamic关键字简化反射实现。下面用例子说明,利用反射计算Person类中方法计算两个数的和。利用反射立马能够写出

1     Person dy = new Person();
2     var p= typeof(Person).GetMethod("Add");
3     Convert.ToInt32(p.Invoke(dy, new object[] { 30, 40 });)

如果利用 dynamic 关键字能够更加精简而且更加优美

1      dynamic dy = new Person();
2      dy.Add(30, 40); 

总结

  (1)利用反射动态创建对象两种方法

    【1】利用Activator.CreateInstance,前提是调用对象的默认无参构造函数

    【2】利用构造器来动态创建对象

  (2)利用dynamic关键字来简化反射实现

时间: 2024-10-14 10:07:48

反射之动态创建对象的相关文章

【C#反射-动态创建对象】

上面博客学习了使用反射查看类型的信息,以及使用反射获取特性对象. 下面使用反射来动态创建对象.首先准备一个Test类: public class TestClass { public TestClass() { Console.WriteLine("这是一个无参构造函数"); } public TestClass(int a, int b) { Console.WriteLine("这是一个有参数构造函数 > a+b=" + (a + b)); } publi

通过反射动态创建对象、方法

之前做的都是获取特性对象,都是查元数据的信息,现在我们可以通过反射开始动态的去创建对象和方法 1.两种调用无参构造函数的方法: 创建一个DemoClass,里面有无参构造函数和有参构造函数 public class DemoClass { public string Name { get; set; } public int Age { get; set; } public DemoClass() { Console.WriteLine("无参构造函数被调用啦"); } public

java反射与动态代理

Java反射与动态代理 Java反射机制可以动态地获取类的结构,动态地调用对象的方法,是java语言一个动态化的机制.java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的耦合性.这些都是java的基础知识,要想成为一名合格的程序猿,必须掌握! Java反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为

.Net——动态创建对象

刚开始看到这个标题的时候其实我也是很难接受的,duang~因为实在想不出什么时候我要去这样子创建对象,干嘛不new一个呢?但根据学习设计模式的经验来说,有时候,不去new对象才是最灵活的做法. 首先,写个小类拿着玩儿: public class Calculator { private int x; private int y; public Calculator() { x = 0; y = 0; Console.WriteLine("Calculator () invoked");

动态创建对象

C#主要支持 5 种动态创建对象的方式: 1. Type.InvokeMember 2. ContructorInfo.Invoke 3. Activator.CreateInstance(Type) 4. Activator.CreateInstance(assemblyName, typeName) 5. Assembly.CreateInstance(typeName) 最快的是方式 3 ,与 Direct Create 的差异在一个数量级之内,约慢 7 倍的水平.其他方式,至少在 40

Java开发人员必懂的基础——反射与动态代理

Java的反射与动态代理是java体系结构中较为底层的知识,初学者可能觉得没有太大的用处,但他们确实著名Spring框架IOC和AOP所用的最重要的内容.当我们需要开发更基础,更广泛的的代码时,就会用到这学知识了. 在此之前,我们先来了解一下java的类加载机制 JVM与类加载机制: /* * 1.JVM:当调用java命令来运行某个java程序时,该命令会启动一个java虚拟机进程,同一个JVM中的所有线程,所有变量都处于同一个进程里,都使用该JVM的内存区 * 2.JVM:运行下面两个测试类

深入浅出MyBatis:反射和动态代理

前三篇详细总结了Mybatis的基本特性.常用配置.映射器,相对于Hibernate,映射器的配置相对复杂,但有很好的灵活性和扩展性,可以应对各种业务场景.熟练掌握这些内容,可以流畅的使用MyBatis进行开发了. 后面准备介绍MyBatis的解析和运行原理以及自定义插件,今天看了书籍的这部分,都会涉及到反射和动态代理这些基础,本篇文章总结下这些,便于理解原理. 通过本篇的介绍,你会了解到: 反射和动态代理是解决什么问题的 Class对象 反射能做什么 动态代理的实现方式:JDK动态代理.CGL

Java反射以及动态代理(上)

在常用的各种框架中,反射与动态代理很常见,也很重要.本篇就对这一小节的内容基础性地总结. 首先需要了解什么是类型信息,以及RTTI与反射的关系与区别. Java中,使用Class对象来表示所有类的对象.利用Class对象来获取类中的成员变量,构造函数以及方法,这些内容我们称之为类型信息.RTTI的含义是,在运行时识别一个对象的类型,但有一个前提,就是类型在编译时必须已知,这样才能用RTTI识别,并利用这些信息做一些有用的事情.但是如果在编译时,程序没有办法获知到这个对象所属的类,怎样才能使用这个

C++ Primer 学习笔记_34_面向对象编程(5)--虚函数与多态(二):纯虚函数、抽象类、虚析构函数、动态创建对象

C++ Primer 学习笔记_34_面向对象编程(5)--虚函数与多态(二):纯虚函数.抽象类.虚析构函数.动态创建对象 一.纯虚函数 1.虚函数是实现多态性的前提 需要在基类中定义共同的接口 接口要定义为虚函数 2.如果基类的接口没办法实现怎么办? 如形状类Shape 解决方法 将这些接口定义为纯虚函数 3.在基类中不能给出有意义的虚函数定义,这时可以把它声明成纯虚函数,把它的定义留给派生类来做 4.定义纯虚函数: class <类名> { virtual <类型> <函