版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、117 特性和反射1.特性 2.内置特性信息3.自定义特性4.浏览元数据5.反射所有类型6.反射一个类型7.反射类型的成员8.MemberInfo9.迟绑定10.反射发送1.动态调用2.接口3.反射发送21 特性n特性是往程序中添加元数据的的机制。n可能的特性目标:包括配件,类,接口,类成员等。n参见AttributeTargets枚举的取值:All, assembly,class,constructor, Delegate ,enum,Event,field,interface,method,modulen可以通过ILDASM进行查看。n反射(reflection)(retrospectio
2、n 回顾, 内省) 是应用程序读取元数据的过程。3n特性是一个对象。表示与程序中某元素(或者特性的目标)相关联的数据。n特性应用于其目标时,将特性信息放在紧贴目标之前的方括号中。 特性 特性目标n一个目标可以有多个特性。42 内置特性信息n常见的内置特性信息包括: 装配件的有关信息。Assemble: COM互操作 Serializable DllImport在C#编写的代码中调用一个外部的其他工具开发的dll中的某函数。比如Win32API。 Conditional 条件编译特性。类似于C中的#if #endif53 自定义特性n假设自定义一个特性用来记录代码的修改记录。以后可以写一个辅助程
3、序来跟踪整个项目的代码修改情况,以便进行项目管理。n在修改过的代码单元中使用如下的特性实例来记录:nBugFixAttribute(323,”Jesse”,”1/1/2005”,” a big bug”n该特性可能出现在类,类成员,接口等等位置。n辅助程序读取程序中的元数据可以进行各种分类,统计等工作。(注释不能做到这点)6n特性也是用类来描述的。所有的特性都派生自System.Attribute类。n描述这个特性类要用到另一个预定义特性AttributeUsage。nAttributeUsage(AttributeUsage( validon, , AllowMultiple=AllowMu
4、ltiple=allowmultiple, , Inherited=Inherited=inherited ) ) nValidon 指定属性可以放置在其上的语言元素(AttributeTargets 值的组合)。默认值为 AttributeTargets.All。 n多个值可以使用OR运算组合起来。nAllowMultipleAllowMultiple表示是否允许一个特性多次应用到同一个元素表示是否允许一个特性多次应用到同一个元素中。中。nInherited Inherited 表示表示属性是否是否由派生类继承nAttributeUsage是应用于属性信息的属性信息.称meta-attrib
5、ute, 它可以提供元元数据(meta-metadata)即关于元数据的数据.7 AttributeUsage( AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property,/此特性可以使用的范围 AllowMultiple = true )/此特性可以多次重复使用 public class BugFixAttribute : System.Attribute/特性类名字一般以Attribu
6、te为后缀。如果省略,编译器自动加上此后缀。 8 private int bugID; private string comment; private string date; private string programmer; public BugFixAttribute ( int bugID, string programmer, string date ) this.bugID = bugID; grammer = programmer; this.date = date; /构造函数。9 / property for named parameter public s
7、tring Comment get return comment; set comment = value; public int BugID get return bugID; public string Date get return date; public string Programmer get return programmer; 10使用特性类来修饰其他类。 BugFixAttribute( 121, Jesse Liberty, 01/03/05 ) BugFixAttribute( 107, Jesse Liberty, 01/04/05, Comment = Fixed
8、off by one errors ) /两个特性的实例 public class MyMath public double DoFunc1( double param1 ) return param1 + DoFunc2( param1 ); public double DoFunc2( double param1 ) return param1 / 3; 使用包含有特性的类:MyMath mm = new MyMath();Console.WriteLine( Calling DoFunc(7). Result: 0,mm.DoFunc1( 7 ) );n辅助程序可以读取这些特性信息。即反
9、射114 浏览元数据n在运行期可以浏览带有特性的类的特性信息。辅助程序可以借此进行关于特性的操作。System.Reflection.MemberInfo inf = typeof( MyMath );/要引入带有特性的类的类型库。 object attributes; attributes = inf. GetCustomAttributes( typeof( BugFixAttribute ), false ); /也要引入特性类的类型库。foreach ( Object attribute in attributes ) BugFixAttribute bfa = ( BugFixAtt
10、ribute ) attribute; Console.WriteLine( nBugID: 0, bfa.BugID ); Console.WriteLine( Programmer: 0, bfa.Programmer ); Console.WriteLine( Date: 0, bfa.Date ); Console.WriteLine( Comment: 0, bfa.Comment ); 125 反射所有类型n反射不仅可以查看元数据,也可以查看类型数据。n如:可以用来对查询一个配件所包含的全部类型: Assembly b=Assembly.LoadFrom (classwithatt
11、r.dll);Type types = b.GetTypes();MessageBox.Show (types.Length.ToString () );foreach ( Type t in types ) MessageBox.Show (t.Name ); 136 反射一个类型也可以只反射某一个指定的类型: Type theType = Type.GetType(System.Int32 ); Console.WriteLine( n Single Type is 0n, theType );147 反射类型的成员n可以反射某类型的所有成员,包括方法,字段等。 MemberInfo mb
12、rInfoArray = theType.GetMembers(); foreach ( MemberInfo mbrInfo in mbrInfoArray ) Console.WriteLine( 0 is a 1, mbrInfo, mbrInfo.MemberType ); n或者使用GetMethods函数反射所有的方法,使用GetFilelds函数反射所有的字段等等。n或者使用GetMethod函数反射指定的方法,使用GetFileld函数反射指定的字段等等。n更一般地使用FindMembers来查找出具有某种特性的成员。n详见msdn15n寻找类型的方法 MemberInfo m
13、brInfoArray = theType.FindMembers( MemberTypes.Method, BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, Type.FilterName, Get* ); foreach ( MemberInfo mbrInfo in mbrInfoArray ) Console.WriteLine( 0 is a 1, mbrInfo, mbrInfo.MemberT
14、ype ); 168 MemberInfonMemberInfo 类是用于获取类的所有成员(构造函数、事件、字段、方法和属性)信息的类的抽象基类。n此类引入所有成员都提供的基本功能。nFindMembers等函数返回一个MemberInfonMemberInfo是MethodInfo, FileldInfo等的基类。GetMember,GetFiled分别返回之。n通过MethodInfo可以动态调用它所反映的方法。即迟绑定。179 迟绑定n早绑定 编译时刻n迟绑定(晚绑定)运行时刻。n灵活性与性能的权衡。n迟绑定用于不经过编译的场合,比如脚本语言。n以下代码需using System.Ref
15、lection;18Type theMathType = Type.GetType( System.Math );Type paramTypes = new Type1; paramTypes0 =Type.GetType( System.Double ); / 查找名字为“Cos”,参数为paramTypes的函数,得到 Cos的 methodinfo 名字“Cos”是猜测的。如猜测失败,虽然编译通过,但运行失败。 MethodInfo CosineInfo = theMathType.GetMethod( Cos, paramTypes ); / 准备参数。 Object paramete
16、rs = new Object1; parameters0 = 45 * ( Math.PI / 180 ); / 45 度 Object returnVal = CosineInfo.Invoke( theMathType, parameters ); /动态调用。 Console.WriteLine(The cosine of a 45 is 0, returnVal );1910 反射发送nReflection emit n支持运行期的类型动态创建n例子:循环与硬编码 Brute Force and Loop DynamicInvoke DynamicInterface Reflecti
17、onEmit20public int DoSum( int n ) /n=20 int result = 0; for ( int i = 1; i = n; i+ ) result += i; return result; /循环体中执行多条指令。 public int DoSum2() return 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20; /只执行一条指令。硬编码的方式比循环的方式快10倍。21 int val = 20, iterations = 1
18、000000;int result = 0;MyMath m = new MyMath();DateTime startTime = DateTime.Now;for(int i=0; iiterations; i+ )result = m.DoSum( val ); /循环计算测试TimeSpan elapsed =DateTime.Now - startTime;Console.WriteLine(Loop: Sum is 0 , result );Console.WriteLine(time is: +elapsed.TotalMilliseconds.ToString() );star
19、tTime = DateTime.Now;for(int i = 0; i compile.out;string frameworkDir =RuntimeEnvironment.GetRuntimeDirectory();psi.Arguments =String.Format( compileString, frameworkDir, fileName );psi.WindowStyle = ProcessWindowStyle.Minimized;Process proc = Process.Start( psi ); /启动进程进行编译proc.WaitForExit( 2000 );
20、/本进程等待2秒。/应该用进程的同步机制,这里是一种临时的处理方法27Assembly a =Assembly.LoadFrom( fileName + .dll );/加载装配件theClass = a.CreateInstance( className );/得到对象theType = a.GetType( className );/得到类File.Delete(fileName + “.cs”); /删除临时的装配件n结果:使用动态调用的方式速度更慢。n原因: 未使用进程的同步机制。(使用同步机制会消除。) 读写硬盘 (使用Emit消除) 迟绑定 (使用接口消除)2810.2 接口n一个
21、能加快速度的方法是把迟绑定改为早绑定。但如下方法是不行的:object theClass = null;theClass = a.CreateInstance( className );/得到对象theClass.ComputeSum();/theClass并不知晓ComputeSum为何物。n 为此定义一个接口:public interface IComputer double ComputeSum(); 29public class ReflectionTest / Type theType = null; /用来保存任何类型,这里保存动态创建的类型。/ object theClass =
22、 null;/用来保存任何对象,这里保存动态创建的对象。IComputer theComputer = null;/成员接口,以后将用来保存动态创建的对象,/此对象类实现了此接口。 public double DoSum( int theValue ) private void GenerateCode( int theVal ) 30public double DoSum( int theValue ) if ( theComputer = null ) GenerateCode( theValue ); return ( theComputer.ComputeSum() ); /不使用迟绑
23、定,而通过接口来进行调用。31 private void GenerateCode( int theVal ) /生成代码,编译,同前,唯一要注意这里编译时要加入对ReflectionTest.exe的引用,以使得编译器知晓Icomputer的定义。 Assembly a = Assembly.LoadFrom( fileName + .dll ); theComputer = ( IComputer ) a.CreateInstance( className );性能会稍有改进。3210.3 反射发送n以上出现性能瓶颈的原因在于硬盘操作。n 进行如下的改进:npublic interface
24、 IComputer int ComputeSum(); public class ReflectionTest IComputer theComputer = null;public double DoSum( int theValue ) /同10.2完全一致。public void GenerateCode( int theValue ) Assembly theAssembly = EmitAssembly( theValue ); theComputer = ( IComputer ) theAssembly.CreateInstance( BruteForceSums ); pri
25、vate Assembly EmitAssembly( int theValue ) /动态创建对象的方法有重大改进!n 33nprivate Assembly EmitAssembly( int theValue )n nAssemblyNamen AssemblyBuildernModuleBuildernTypeBuildernAddInterfaceImplementationn MethodBuildernILGeneratorn generator.Emit34 AssemblyName assemblyName = new AssemblyName(); assemblyName
26、.Name = “DoSumAssembly”; /配件的名字AssemblyBuilder newAssembly = Thread.GetDomain().DefineDynamicAssembly( assemblyName, AssemblyBuilderAccess.Run ); ModuleBuilder newModule = newAssembly.DefineDynamicModule( Sum );/生成单模块的配件TypeBuilder myType = newModule.DefineType( BruteForceSums, TypeAttributes.Public
27、 );/在配件中定义一个类myType.AddInterfaceImplementation(typeof( IComputer ) );/该类实现接口 IComputer. 35/为类定义一个方法,方法具有具有我们希望的签名。 Type paramTypes = new Type0; Type returnType = typeof( int ); MethodBuilder simpleMethod = myType.DefineMethod( ComputeSum, MethodAttributes.Public | MethodAttributes.Virtual, returnType, paramTypes ); / 获取一个 ILGenerator.( 中间语言产生器)以产生中间语言ILGenerator generator = simpleMethod.GetILGenerator();/OpCodes类的OpCode类型的静态字段Ldc_I4;表示将所提供的 int32 类型的值作为 int3
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- JJF 2181-2024塑料薄膜和薄片氧气透过率测试仪校准规范
- 2024年版简易个人向公司借款合同模板
- 2024年版权授权费用协议
- 杞县特色小镇投资建设研究报告
- 硫酸盐项目申请报告可行性研究报告
- 中秋节假日作文大全10篇
- 水浒传每章读书笔记
- 双十一促销活动策划方案8篇
- 保护树木的建议书模板汇编十篇
- 法律执法课程设计
- 普外科医疗组长竞聘演讲
- 北京市朝阳区2022-2023学年三年级上学期英语期末试卷
- 哔哩哔哩MATES人群资产经营白皮书【哔哩哔哩】
- 【历史】第一、二单元测试题2024~2025学年统编版七年级历史上册
- 婚姻家庭规划
- 认识实习报告(10篇)
- 【MOOC】内科护理学-中山大学 中国大学慕课MOOC答案
- 2024年商业地产买卖合同样本
- 2023-2024学年广东省深圳市福田区七年级(上)期末英语试卷
- 双碳全景系列培训第一章碳达峰、碳中和
- 【企业盈利能力探析的国内外文献综述2400字】
评论
0/150
提交评论