反射是架构师必会的基础,因为任何一个被设计出来的框架,都要使用反射。反射也是最隐蔽的语法,因为反射写出来后,通常它会被直接封装,然后调用者就只负责使用,不再关注他的具体实现。这与它的特性有关,因为反射就是为了减少代码冗余而存在的,所以,看不见很正常。
反射的定义
官方定义:反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。
看不懂?没关系,我们把它翻译成人类可理解的语言。
C#编程语言中,最常使用的是类和类中的函数和属性。正向调用的方法是,创建类,然后用类创建一个对象。接下来就可以用这个对象调用类中的方法和属性了。
而反射,就是相对于这种正向调用的存在。即,它是反向调用。
反射可以通过类名的字符串来创建类,可以通过函数名的字符串和属性名的字符串,来调用类下的函数和属性。
有同学会问了, 既然正向可以调用,那么反向调用干什么呢?
会有这种问题的同学,先别着急,继续往下看,反射既然存在,就必然有存在的道理。
在代码中我们看到,反射时传递了字符串"Syntax.Kiba",然后通过解析字符串,获取到了该字符串对应的类的类型,最后再借助Activator来辅助创建类的实例。
其中字符串"Syntax.Kiba"是一个完全限定名。什么是完全限定名?完全限定名就是命名空间+类名。在反射的时候,需要我们传递完全限定名来确定到底要去哪个命名空间,找哪个类。
在代码中我们还可以看到,获取类型的方式有两种,一种是较复杂的,一种是简单的。
GetType2方法是简单的获取类别,通过Type直接就解析了字符串。而GetType则先进行了加载Assembly(组件),然后再由组件获取类型。
两者有什么区别呢?
区别是,用Type直接解析,只能解析当前命名空间下的类。如果该类存在于引用的DLL中,就解析不了。
而GetType方法中的[Assembly.Load指定了程序集名],所以,在反射时,就会去指定的命名空间里找对应的类。这样就能找到非本程序集下的类了。
[Assembly.Load指定了程序集名]这句话不好理解?
没关系,换个表达,Assembly.Load指定了命名空间的名称,所以反射时,会去这个命名空间里找类,这样是不是就好理解了。