深刻理解反射(Reflection)
最近公司在搞自动化测试,由于版权问题,无法用 ’录制脚本‘ 进行,也就没法用 VS 自带的 UITest 框架(蛋疼), 所以只能开源的 FlaUI 框架来搞了。其中不可避免的涉及到反射的应用,但自己有些概念还是有点模糊不清, 干脆集中将自己个人的理解整理一下。
一、前提
要理解反射首先要理解 特性 的概念,因为反射通常需要获取用户自定义属性。
特性(Attribute)
概念: 用于在运行时传递程序中各种元素(类,方法等)的行为信息的声明性标签。
声明方法:在它所应用的元素(类, 方法等)面前防止方框号([ ]), ig. [SayHelloAttribute]。
主要作用:对应用的元素添加元数据, 程序可以使用反射检查获取自己的元数据或者其它元素内的元数据。
可以这么理解元数据的概念:程序集中所有关于声明类的数据信息(成员函数, 属性, 方法调用)等都储存在元数据里面(pdb 文件)。
如果还不理解特性的概念, 点这里 https://en.wikipedia.org/wiki/Attribute_(computing)
二、 概念
反射: 指程序可以访问、检测和修改它本身状态或行为的一种动作。
作用: 通过反射, 可以在运行时获取指定程序集(dll 集合) 每一个类型(包括类、结构、委托、接口等)的成员(方法、事件、属性等)。
三、用途
反射可以作用在程序集上, 程序集包含模块, 模块包含类型,类型又包含成员, 反射可以对封装程序集、模块、类以及成员进行操作。通常,使用反射动态的创建类型的实例, 将类型绑定到现有对象(或从现有对象获取类型), 然后调用类型的方法。
最常见用途如下:
1、使用 Assembly 定义和加载程序集, 并提取指定的类型集合。
如下所示, 加载 "ReflectionTest.exe" , 提取程序中有 “HelloAttribute" 属性的类。
1 Assembly a = Assembly.Load("ReflectionTest.exe"); 2 // 当 dll 与 类唯一时, 以下两种获取 type 方式等效 3 // 与下面方式等效 Type assType = typeof(HelloWorld); 4 Type[] assTypes = a.GetTypes(); 5 foreach (Type assType in assTypes) 6 { 7 object[] attributes = assType.GetCustomAttributes(typeof(HelloAttribute), false); 8 }
2、使用 MethodInfo 了解方法的名称, 返回类型,参数 以及实现信息。
// HellowWord 是一个类
1 Type = Typeof(HelloWord) 2 var m = t.GetMethods(); 3 foreach (MethodInfo mInfo in m) 4 { 5 // 此处考虑了 attributeMutiple = true 的情况 6 foreach (Attribute aa in mInfo.GetCustomAttributes(true)) 7 { 8 HelloAttribute d = aa as HelloAttribute; 9 if (null != d) 10 { 11 Console.WriteLine("the method is you wanted: {0}", m); 12 } 13 } 14 }
3、实例化对象, 调用方法
1 Type t = typeof(HelloWorld); 2 // 实例化 HelloWorld 3 Object obj = Activator.CreateInstance(t); 4 5 // 调用 Hello 方法(’Hello‘ 方法在 ’HelloWorld‘ 类中已经实现过) 6 MethodInfo custHello = t.GetMethod("Hello") 7 custHello.Invoke(parame) // parame 指的是对应的参数。
本次用到的方法主要是以上三种,这次也先写这么多,后期用到其它方法,再来更新。