C#中所有的引用类型的实例都需要在运行时动态创建,创建对象实例最常见的办法就是使用new操作符,使用new操作符就需要在编译器明确的知道要创建的对象的类型,如果在编译器并不能明确,就需要用到反射技术,例如:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
之所以不能直接使用new,就是因为new后面的类型参数在编译器是不知道的,那么就需要在运行的时候动态的创建出与new相配合的代码。这类似于在Javascript中使用eval函数:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
System.Reflection.Emit.AssemblyBuilder:用来动态创建程序集
System.Reflection.Emit.ModuleBuilder:用来动态创建模块
System.Reflection.Emit.TypeBuilder:用来动态创建类型
System.Reflection.Emit.MethodBuilder:用来动态创建方法
这里我的设计思想是,首先创建一个抽象基类(Creator类),它声明了一个用于动态创建需要的对象实例的抽象方法,在运行时根据需要动态的创建出这个抽象类的子类,并动态实现这个抽象方法,编写出用于创建对象的代码。在基类中提供一些静态方法来实现子类的创建过程,并对外提供可调用的方法。这是抽象工厂模式的一种实现。基类的声明如下:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
New方法里面首先要动态的创建程序集和模块:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
然后根据这个方法信息创建出子类的同名方法:
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
注意这里指定方法属性时需要去除掉基类方法的抽象属性,否则在创建实例时会失败,其他地方都完全和基类方法一样。下面要在被创建对象的类型中查找适当的构造函数。查找的方法是针对每一个构造函数,检查它的参数个数和参数类型与所传入的参数信息是否相容,如果找不到完全相容的构造函数,那么说明用户传入的参数有误,需要抛出异常:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)