今天学到反射,看到如图所示的通过反射创建对象的代码,通过type接收dll文件中指定类的内部信息,然后通过Activator的CreateInstance方法来根据type创建对象,我想问的就是,既然都能拿到内部信息了,那为何不直接拿到这个类,通过new的方式创建对象呢?
今天学到反射,看到如图所示的通过反射创建对象的代码,通过type接收dll文件中指定类的内部信息,然后通过Activator的CreateInstance方法来根据type创建对象,我想问的就是,既然都能拿到内部信息了,那为何不直接拿到这个类,通过new的方式创建对象呢?
问题在于,怎么直接拿到这个类?如果能直接拿到这个类用于
new
运算符,哪里还需要反射?从处理时期来说,都是在运行时产生对象,但是
new
运算符会在编译期进行静态检查,CreateInstance()
是在运行时进行动态检查 …… 比如说type
对应的类没有无参构造函数,但是使用了CreateInstance(type)
来构造对象,在编译的时候是没问题的,但在运行的时候会抛出异常。先想像一下,创建对象的过程是什么?
是使用
new
运算符来 构造对象 ——new
运算符实际是调用了类的构造函数(或者叫构造方法)。通过反射,可以拿到一个
Type
。但是从这个 Type 没办法简单的构造出对应的对象来,因为这个 Type 虽然描述了你想要的那个类的信息,但编译器并不知道它是什么,只有运行时知道。new
运算符后面接的是一个构造函数(或简单地认为是一个类),在运行时,没有办法使用new
运算符,从找到的类型描述(Type 对象)构造对象。如果要动态的构造对象,需要先找到 Type 中描述的构造函数。
Type
有三个方法可以拿到构造函数:GetConstructor, GetConstructors 和 GetConstructorImpl。比较常用的是第一个,找到正确的构造函数之后,会得到一个ConstructorInfo
对象,在这个对象上调用Invoke
方法并传入正确的参数,可以创建所需要的实例。这个过程很清晰,就是代码写起来比较长,而且可能还要加入一些代码来处理容错。
不过既然构造实例是这么复杂的一个过程,而且步骤基本上没啥变化,为啥不写一个工具函数来简化处理呢 ——
Activator.CreateInstance(...)
系列方法不就干这个事情的么?