版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、117 特性和反射1.特性 2.內(nèi)置特性信息3.自定義特性4.瀏覽元數(shù)據(jù)5.反射所有類型6.反射一個類型7.反射類型的成員8.MemberInfo9.遲綁定10.反射發(fā)送1.動態(tài)調(diào)用2.接口3.反射發(fā)送21 特性n特性是往程序中添加元數(shù)據(jù)的的機制。n可能的特性目標:包括配件,類,接口,類成員等。n參見AttributeTargets枚舉的取值:All, assembly,class,constructor, Delegate ,enum,Event,field,interface,method,modulen可以通過ILDASM進行查看。n反射(reflection)(retrospectio
2、n 回顧, 內(nèi)省) 是應用程序讀取元數(shù)據(jù)的過程。3n特性是一個對象。表示與程序中某元素(或者特性的目標)相關(guān)聯(lián)的數(shù)據(jù)。n特性應用于其目標時,將特性信息放在緊貼目標之前的方括號中。 特性 特性目標n一個目標可以有多個特性。42 內(nèi)置特性信息n常見的內(nèi)置特性信息包括: 裝配件的有關(guān)信息。Assemble: COM互操作 Serializable DllImport在C#編寫的代碼中調(diào)用一個外部的其他工具開發(fā)的dll中的某函數(shù)。比如Win32API。 Conditional 條件編譯特性。類似于C中的#if #endif53 自定義特性n假設(shè)自定義一個特性用來記錄代碼的修改記錄。以后可以寫一個輔助程
3、序來跟蹤整個項目的代碼修改情況,以便進行項目管理。n在修改過的代碼單元中使用如下的特性實例來記錄:nBugFixAttribute(323,”Jesse”,”1/1/2005”,” a big bug”n該特性可能出現(xiàn)在類,類成員,接口等等位置。n輔助程序讀取程序中的元數(shù)據(jù)可以進行各種分類,統(tǒng)計等工作。(注釋不能做到這點)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, 它可以提供元元數(shù)據(jù)(meta-metadata)即關(guān)于元數(shù)據(jù)的數(shù)據(jù).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; /構(gòu)造函數(shù)。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 瀏覽元數(shù)據(jù)n在運行期可以瀏覽帶有特性的類的特性信息。輔助程序可以借此進行關(guā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反射不僅可以查看元數(shù)據(jù),也可以查看類型數(shù)據(jù)。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函數(shù)反射所有的方法,使用GetFilelds函數(shù)反射所有的字段等等。n或者使用GetMethod函數(shù)反射指定的方法,使用GetFileld函數(shù)反射指定的字段等等。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 類是用于獲取類的所有成員(構(gòu)造函數(shù)、事件、字段、方法和屬性)信息的類的抽象基類。n此類引入所有成員都提供的基本功能。nFindMembers等函數(shù)返回一個MemberInfonMemberInfo是MethodInfo, FileldInfo等的基類。GetMember,GetFiled分別返回之。n通過MethodInfo可以動態(tài)調(diào)用它所反映的方法。即遲綁定。179 遲綁定n早綁定 編譯時刻n遲綁定(晚綁定)運行時刻。n靈活性與性能的權(quán)衡。n遲綁定用于不經(jīng)過編譯的場合,比如腳本語言。n以下代碼需using System.Ref
15、lection;18Type theMathType = Type.GetType( System.Math );Type paramTypes = new Type1; paramTypes0 =Type.GetType( System.Double ); / 查找名字為“Cos”,參數(shù)為paramTypes的函數(shù),得到 Cos的 methodinfo 名字“Cos”是猜測的。如猜測失敗,雖然編譯通過,但運行失敗。 MethodInfo CosineInfo = theMathType.GetMethod( Cos, paramTypes ); / 準備參數(shù)。 Object paramete
16、rs = new Object1; parameters0 = 45 * ( Math.PI / 180 ); / 45 度 Object returnVal = CosineInfo.Invoke( theMathType, parameters ); /動態(tài)調(diào)用。 Console.WriteLine(The cosine of a 45 is 0, returnVal );1910 反射發(fā)送nReflection emit n支持運行期的類型動態(tài)創(chuàng)建n例子:循環(huá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; /循環(huán)體中執(zhí)行多條指令。 public int DoSum2() return 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20; /只執(zhí)行一條指令。硬編碼的方式比循環(huán)的方式快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 ); /循環(huán)計算測試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結(jié)果:使用動態(tài)調(diào)用的方式速度更慢。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; /用來保存任何類型,這里保存動態(tài)創(chuàng)建的類型。/ object theClass =
22、 null;/用來保存任何對象,這里保存動態(tài)創(chuàng)建的對象。IComputer theComputer = null;/成員接口,以后將用來保存動態(tài)創(chuàng)建的對象,/此對象類實現(xiàn)了此接口。 public double DoSum( int theValue ) private void GenerateCode( int theVal ) 30public double DoSum( int theValue ) if ( theComputer = null ) GenerateCode( theValue ); return ( theComputer.ComputeSum() ); /不使用遲綁
23、定,而通過接口來進行調(diào)用。31 private void GenerateCode( int theVal ) /生成代碼,編譯,同前,唯一要注意這里編譯時要加入對ReflectionTest.exe的引用,以使得編譯器知曉Icomputer的定義。 Assembly a = Assembly.LoadFrom( fileName + .dll ); theComputer = ( IComputer ) a.CreateInstance( className );性能會稍有改進。3210.3 反射發(fā)送n以上出現(xià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 ) /動態(tài)創(chuàng)建對象的方法有重大改進!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 ) );/該類實現(xiàn)接口 IComputer. 35/為類定義一個方法,方法具有具有我們希望的簽名。 Type paramTypes = new Type0; Type returnType = typeof( int ); MethodBuilder simpleMethod = myType.DefineMethod( ComputeSum, MethodAttributes.Public | MethodAttributes.Virtual, returnType, paramTypes ); / 獲取一個 ILGenerator.( 中間語言產(chǎn)生器)以產(chǎn)生中間語言ILGenerator generator = simpleMethod.GetILGenerator();/OpCodes類的OpCode類型的靜態(tài)字段Ldc_I4;表示將所提供的 int32 類型的值作為 int3
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2021成都中考語文試卷解析(物超所值-名師詳解)要點
- 湖北省新高考聯(lián)考協(xié)作體2024-2025學年高一上學期11月期中英語試題(無答案)
- 山東省濟南市鋼城區(qū)2024-2025學年四年級上學期11月期中數(shù)學試題
- 垃圾處理公司配電房安裝合同
- 綠色公園種樹施工合同范文
- 煤炭科研質(zhì)量要求
- 土地資源合理利用M變更管理實施
- 學校采光井施工項目
- 河道整治彩鋼板安裝協(xié)議
- 物業(yè)管理指導員招聘協(xié)議
- 燃燒與爆炸理論課件
- 2022中考語文熱點聚焦:航天科技( 有答案)
- 第1章 復合材料概論
- 中藥材種植課件
- 大貨車安全隱患排查方案及流程
- 業(yè)務經(jīng)營弄虛作假專項治理心得體會范文
- 無人機飛行操作手冊
- 癌癥治療指南手冊
- 醫(yī)美行業(yè)發(fā)展趨勢
- 自發(fā)性腹膜炎的護理查房課件
- 2023年度中國游戲產(chǎn)業(yè)報告
評論
0/150
提交評論