关键词:C#、反射(Reflection)
导读
在传统的静态语言中,被引用的所有类、所有方法都需要在应用编译时严格的声明和定义,但是随着软件规模的增大、业务场景的愈加复杂,这种方式已经无法满足部分业务变更较频繁、扩展性要求较高的场景。目前大多主流语言都提供了动态调用组件的实现方式,其中.NET平台提供了反射机制解决该类问题。
.NET平台的反射机制提供的功能主要包括:运行时动态加载指定的链接库、获取任意类的字段/属性/方法的元数据(包括非公共权限)、运行时使用类名动态创建任意类的实例、运行时修改任意对象的指定字段(包括私有字段)、运行时使用方法名调用任意类型的方法。
使用到反射的应用场景很多,例如VS的winform界面设计器,因为设计器在实现时,无法预知待加载的控件【1】。
反射的定义
反射(Reflection)是审查元数据并收集关于它的类型信息的能力【2】。这是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:程序集(Assembly)、模块(Module)、类(class)组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息。
反射的使用
反射中使用一组类的定义实现对反射对象的管理,这些类大都被定义在System.Reflection命名空间下,其中经常用到的类主要包括:
System.Reflection.Assembly类:该类用来维护当前已加载的某个程序集的所有元数据信息。使用该类可以获取当前程序集的所有描述信息、当前程序集所在的文件路径、当前程序集内所有类的Type对象。同时该类提供的静态方法可以实现从指定文件加载程序集的功能。该类的详细描述参见该链接(Assembly Class)。
System.Type类:该类用于维护某个类型的所有元数据信息,一种类型的Type类在当前应用域内有且只有一个实例。使用该类可以获取当前类的所有描述信息和类中定义的所有构造方法信息(ConstructorInfo)、字段信息(FieldInfo)、属性信息(PropertyInfo)、方法信息(MethodInfo)。该类的详细描述参见该链接(Type Class)。
System.Reflection.ConstructorInfo类:该类用于维护指定类的某个构造方法的元数据信息。使用该类可以获取当前构造方法的名称、参数签名、调用入口等。该类的详细描述参见该链接(ConstructorInfo)。
System.FieldInfo和System.PropertyInfo类:这两个类分别用以维护指定类型的某个字段属性信息。使用这两个类可以分别获取当前字段/属性的名称、类型、元数据信息、Get方法和Set方法的调用入口。这两个类的详细描述参见该链接(FieldInfo Class)(PropertyInfo Class)。
System.Reflection.MethodInfo类:该类用于维护指定类的某个方法的元数据信息。使用该类可以获取当前方法的名称、参数签名、调用入口等。该类的详细描述参见该链接(MethodInfo)。
下面是一个反射的简单例子。该例子的代码中完成了动态加载简仪JYUSB61902驱动、创建模拟采集任务实例并配置采样率的功能。
反射的优点
作为.Net中较为重要的机制,有了反射我们就可以得到.Net中每一个类型的相关信息,简单的来说就是通过反射获取成员变量。它的一些方法,属性,构造函数以及参数等等。如果获得了构造函数的信息,即可直接创建对象,即使这个对象的类型在编译时还不可访问。这样大大提高了程序的灵活性与可扩展性,
反射对于需要访问程序元数据中的特性,检查和实例化程序集中的类型,在运行时构建新类型,执行后期绑定,访问在运行时创建的类型上的方法等情况都提供了便利。
反射的缺点
反射在运行时加载的特征可以带来极大的灵活性,同时运行时加载和灵活调用的方式也导致了反射的缺点。
运行时加载的特性导致反射的性能和直接调用的方式相比较低,该性能的降低很大程度上源于反射方法在执行前需要在CLR中获取当前方法的描述类,特别是在频繁获取ConstructorInfo、FieldInfo、PropertyInfo和MethodInfo时这种性能的降低愈加明显。对性能较敏感的代码块可以缓存这些对象达到一定程度降低性能损失的目标。
反射对组件的调用都是使用间接调用,某个组件某个功能的调用并不是显式的被执行,导致代码的逻辑比直接调用更加复杂和隐晦、异常的处理更加复杂,会给软件后续的维护和更新带来很大的风险。
基于以上所陈述的缺点,反射只应被应用于必须使用动态特性的场景。
参考
Copyright © 2016-2024 JYTEK All Rights Reserved.