第7章泛型和反射_第1頁
第7章泛型和反射_第2頁
第7章泛型和反射_第3頁
第7章泛型和反射_第4頁
第7章泛型和反射_第5頁
已閱讀5頁,還剩52頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、7.1 7.1 泛泛 型型7.2 7.2 反反 射射所謂泛型,是指通過參數(shù)化類型來實現(xiàn)在同一份代碼所謂泛型,是指通過參數(shù)化類型來實現(xiàn)在同一份代碼上操作多種數(shù)據(jù)類型,泛型編程是一種編程范式,它利用上操作多種數(shù)據(jù)類型,泛型編程是一種編程范式,它利用“參數(shù)化類型參數(shù)化類型”將類型抽象化,從而實現(xiàn)更為靈活的復(fù)用。將類型抽象化,從而實現(xiàn)更為靈活的復(fù)用。泛型類型和普通類型的區(qū)別在于泛型類型與一組類型參數(shù)泛型類型和普通類型的區(qū)別在于泛型類型與一組類型參數(shù)或類型變量關(guān)聯(lián)?;蝾愋妥兞筷P(guān)聯(lián)。C#C#泛型能力是由泛型能力是由CLRCLR在運行時支持,區(qū)別于在運行時支持,區(qū)別于C+C+的編譯的編譯時模板機制和時模板機

2、制和JavaJava的編譯時的的編譯時的“搽拭法搽拭法”。這使得泛型能。這使得泛型能力可以在各個支持力可以在各個支持CLRCLR的語言之間進行無縫的互操作。的語言之間進行無縫的互操作。7.1.1 7.1.1 什么是泛型什么是泛型數(shù)據(jù)的抽象:數(shù)據(jù)的抽象:int MAX(int a,int b) return ab?a:b; double MAX1(double a,double b) return ab?a:b; int MAX(int a,int b) return ab?a:b; double MAX(double a,double b) return ab?a:b; 重載重載數(shù)據(jù)類型的抽象

3、:數(shù)據(jù)類型的抽象: T MAX(T a,T b) return ab?a:b; 泛型泛型int、double數(shù)據(jù)數(shù)據(jù)通常先聲明泛型,然后通過類型實例化來使用泛型。通常先聲明泛型,然后通過類型實例化來使用泛型。定義泛型的語法格式如下:定義泛型的語法格式如下:訪問修飾符訪問修飾符返回類型返回類型 泛型名稱泛型名稱其中,其中,“泛型名稱泛型名稱”要符合標(biāo)識符的定義。尖括號要符合標(biāo)識符的定義。尖括號表示類型參數(shù)列表,可以包含一個或多個類型參數(shù),如表示類型參數(shù)列表,可以包含一個或多個類型參數(shù),如。7.1.2 7.1.2 泛型的聲明和使用泛型的聲明和使用C#中常用的泛型有泛型類和泛型方法,例如:中常用的泛

4、型有泛型類和泛型方法,例如:class Stack/聲明泛型類聲明泛型類 T dataMaxSize;int top;void swap(ref T a,ref T b)/定義泛型方法定義泛型方法 T tmp = a;a = b;b = tmp;【例例7.1】 分析以下程序的執(zhí)行結(jié)果。分析以下程序的執(zhí)行結(jié)果。using System;namespace proj7_1 class Student /學(xué)生類學(xué)生類 int sno; /學(xué)號學(xué)號 string sname; /姓名姓名 public Student() public Student(int no, string name) sno

5、= no; sname = name; public void Dispstudent()/輸出學(xué)生對象輸出學(xué)生對象 Console.Write(0:1 ,sno,sname); class Teacher /教師類教師類 int tno; /編號編號 string tname; /姓名姓名 public Teacher() public Teacher(int no, string name) tno = no; tname = name; public void Dispteacher()/輸出教師對象輸出教師對象 Console.Write(0:1 , tno, tname); clas

6、s Stack/聲明棧泛型類聲明棧泛型類 int maxsize;/棧中元素最多個數(shù)棧中元素最多個數(shù) T data;/存放棧中存放棧中T類型的元素類型的元素 int top;/棧頂指針棧頂指針 public Stack()/構(gòu)造函數(shù)構(gòu)造函數(shù) maxsize = 10; data = new Tmaxsize; top = -1; public bool StackEmpty()/判斷??辗椒ㄅ袛鄺?辗椒?return top = -1; public bool Push(T e)/元素元素e進棧方法進棧方法 if (top = maxsize - 1)/棧滿返回棧滿返回false return

7、 false; top+; datatop = e; return true; public bool Pop(ref T e)/元素出棧方法元素出棧方法 if (top = -1)/棧空返回??辗祷豧alse return false; e = datatop; top-; return true; class Program static void Main(string args) /-整數(shù)棧操作整數(shù)棧操作-int e = 0; Stack s1 = new Stack(); /定義整數(shù)棧定義整數(shù)棧 s1.Push(1); /進棧進棧3個整數(shù)個整數(shù) s1.Push(2); s1.Push

8、(3); Console.Write(整數(shù)棧出棧次序:整數(shù)棧出棧次序:); while (!s1.StackEmpty()/棧不空時出棧元素棧不空時出棧元素 s1.Pop(ref e); Console.Write(0 , e); Console.WriteLine(); /-實數(shù)棧操作實數(shù)棧操作- double d= 0; Stack s2 = new Stack();/定義實數(shù)棧定義實數(shù)棧 s2.Push(2.5);/進棧進棧3個實數(shù)個實數(shù) s2.Push(3.8); s2.Push(5.9); Console.Write(實數(shù)棧出棧次序:實數(shù)棧出棧次序:); while (!s2.Sta

9、ckEmpty()/棧不空時出棧元素棧不空時出棧元素 s2.Pop(ref d); Console.Write(0 , d); Console.WriteLine(); /-學(xué)生對象棧操作學(xué)生對象棧操作- Student st =new Student(); Stack s3 = new Stack();/定義學(xué)生棧定義學(xué)生棧 s3.Push(new Student(1,Student1);/進棧進棧3個學(xué)生對象個學(xué)生對象 s3.Push(new Student(2,Student2); s3.Push(new Student(3,Student3); Console.Write(學(xué)生對象棧出

10、棧次序:學(xué)生對象棧出棧次序:); while (!s3.StackEmpty()/棧不空時出棧元素棧不空時出棧元素 s3.Pop(ref st); st.Dispstudent(); Console.WriteLine(); /-教師對象棧操作教師對象棧操作- Teacher te = new Teacher(); Stack s4 = new Stack();/定義教師棧定義教師棧 s4.Push(new Teacher(1, Teacher1); /進棧進棧3個教師對象個教師對象 s4.Push(new Teacher(2, Teacher2); s4.Push(new Teacher(3

11、, Teacher3); Console.Write(教師對象棧出棧次序:教師對象棧出棧次序:); while (!s4.StackEmpty()/棧不空時出棧元素棧不空時出棧元素 s4.Pop(ref te); te.Dispteacher(); Console.WriteLine(); 本程序先聲明本程序先聲明Student和和Teacher兩個類,再聲明一個兩個類,再聲明一個泛型棧泛型棧Stack,然后實例化為整數(shù)棧,然后實例化為整數(shù)棧s1、實數(shù)棧、實數(shù)棧s2、學(xué)、學(xué)生對象棧生對象棧s3和教師對象棧和教師對象棧s4,各自進棧,各自進棧3個元素后并出棧,個元素后并出棧,程序執(zhí)行結(jié)果如圖程序

12、執(zhí)行結(jié)果如圖7.2所示。所示。7.1.3 7.1.3 泛型的泛型的MSILMSIL代碼分析代碼分析 與與.NET Framework同時發(fā)布的中間語言反匯編工具同時發(fā)布的中間語言反匯編工具(ildasm.exe)可以加載任意的)可以加載任意的.NET程序集并分析它的內(nèi)程序集并分析它的內(nèi)容,包括關(guān)聯(lián)的清單、容,包括關(guān)聯(lián)的清單、MSIL代碼和類型元數(shù)據(jù)。代碼和類型元數(shù)據(jù)。 在命令行方式下進入在命令行方式下進入ildasm.exe所在的文件夾,鍵入所在的文件夾,鍵入ildasm命令,運行該程序,出現(xiàn)一個命令,運行該程序,出現(xiàn)一個“IL DASM”對話框,對話框,選擇選擇“文件文件|打開打開”命令。命

13、令。 選擇例選擇例7.1的程序的程序proj7-1.exe(位于(位于“D:C#程序程序ch7proj7-1proj7-1binDebug”文件夾中),便以樹狀圖文件夾中),便以樹狀圖展示該程序集的結(jié)構(gòu),展開所有項的結(jié)果如圖展示該程序集的結(jié)構(gòu),展開所有項的結(jié)果如圖7.3所示。所示。從例從例7.1程序的中間語言代碼中可以看到如下要點。程序的中間語言代碼中可以看到如下要點。1. 編譯方式編譯方式 第一輪編譯時,編譯器只為第一輪編譯時,編譯器只為Stack產(chǎn)生產(chǎn)生“泛型版泛型版”的的IL代碼與元數(shù)據(jù),并不進行泛型的實例化,代碼與元數(shù)據(jù),并不進行泛型的實例化,T在中間只在中間只充當(dāng)占位符。例如,在充當(dāng)

14、占位符。例如,在Stack的構(gòu)造函數(shù)中占位符顯示的構(gòu)造函數(shù)中占位符顯示為為。 在在JIT編譯時,當(dāng)編譯時,當(dāng)JIT編譯器第一次遇到編譯器第一次遇到Stack時,時,將用將用int替換替換“范型版范型版”IL代碼與元數(shù)據(jù)中的代碼與元數(shù)據(jù)中的T,即進行泛,即進行泛型類型的實例化。例如,型類型的實例化。例如,Main函數(shù)中顯示的函數(shù)中顯示的。2. 2. 引用類型作為參數(shù)和值類型作為參數(shù)引用類型作為參數(shù)和值類型作為參數(shù) CLR為為所有類型參數(shù)為所有類型參數(shù)為“引用類型引用類型”的泛型類型產(chǎn)生的泛型類型產(chǎn)生同一份代碼同一份代碼;但是如果;但是如果類型參數(shù)為類型參數(shù)為“值類型值類型”,對每一個,對每一個不

15、同的不同的“值類型值類型”,CLR將為其產(chǎn)生一份獨立的代碼將為其產(chǎn)生一份獨立的代碼,這,這里的里的s3和和s4的的idloc.s的地址相同,都是的地址相同,都是CS$4$0000。 因為實例化一個引用類型的泛型,它在內(nèi)存中分配的因為實例化一個引用類型的泛型,它在內(nèi)存中分配的大小是一樣的,但是當(dāng)實例化一個值類型的時候,在內(nèi)存大小是一樣的,但是當(dāng)實例化一個值類型的時候,在內(nèi)存中分配的大小是不一樣的。這樣做的目的是盡可能減小代中分配的大小是不一樣的。這樣做的目的是盡可能減小代碼量。碼量。7.1.4 7.1.4 類型參數(shù)的約束類型參數(shù)的約束 在泛型類型或方法定義中,類型參數(shù)是在實例化泛型類在泛型類型或

16、方法定義中,類型參數(shù)是在實例化泛型類型的變量時指定的特定類型的占位符。型的變量時指定的特定類型的占位符。 那么,類型參數(shù)是不是任何類型呢?結(jié)論是否定的。那么,類型參數(shù)是不是任何類型呢?結(jié)論是否定的。例如,聲明以下泛型類型:例如,聲明以下泛型類型:class MyGTypestatic public bool LessThan(T1 obj1, T2 obj2) return obj1 obj2; 在編譯時,系統(tǒng)指出在編譯時,系統(tǒng)指出“運算符運算符無法應(yīng)用于無法應(yīng)用于T1和和T2類型類型的操作數(shù)的操作數(shù)”的錯誤。如果它是正確的,在實例化為的錯誤。如果它是正確的,在實例化為MyGType時,一個整

17、數(shù)和一個字符串怎么比較時,一個整數(shù)和一個字符串怎么比較呢?甚至在實例化為呢?甚至在實例化為MyGType時,一個整數(shù)時,一個整數(shù)和一個對象怎么比較呢?和一個對象怎么比較呢? 為了解決這個問題,為了解決這個問題,C#提出了類型參數(shù)的約束的概念。提出了類型參數(shù)的約束的概念。通過約束檢查泛型列表中的某個項以確定它是否有效。通過約束檢查泛型列表中的某個項以確定它是否有效。 例如,約束告訴編譯器:僅此類型的對象或從此類型派生例如,約束告訴編譯器:僅此類型的對象或從此類型派生的對象才可用作類型參數(shù)。一旦編譯器有了這個保證,它就的對象才可用作類型參數(shù)。一旦編譯器有了這個保證,它就能夠允許在泛型類中調(diào)用該類型

18、的方法。能夠允許在泛型類中調(diào)用該類型的方法。 約束是使用上下文關(guān)鍵字約束是使用上下文關(guān)鍵字 where 應(yīng)用的。應(yīng)用的。where子句的一子句的一般格式如下:般格式如下: where 類型參數(shù):約束類型參數(shù):約束1,約束,約束2, 例如,以下泛型有例如,以下泛型有3個類型參數(shù),個類型參數(shù),T1是未綁定的(沒有是未綁定的(沒有約束),約束),T2只有只有MyClass1類型或從它派生的類或類型或從它派生的類或MyClass2類型或從它派生的類才能用作類型實參,類型或從它派生的類才能用作類型實參,T3只有只有MyClass3類型或從它派生的類才能用作類型實參:類型或從它派生的類才能用作類型實參:c

19、lass MyClass where T2:MyClass1,MyClass2 T3:MyClass3 這樣在對類型參數(shù)的類型種類施加限制后,如果使用這樣在對類型參數(shù)的類型種類施加限制后,如果使用該泛型的代碼嘗試使用某個約束所不允許的類型來實例化該泛型的代碼嘗試使用某個約束所不允許的類型來實例化類,則會產(chǎn)生編譯時錯誤。類,則會產(chǎn)生編譯時錯誤。7.1.5 7.1.5 泛型的繼承泛型的繼承 C#除了可以單獨聲明泛型類型外,也可以在基類中除了可以單獨聲明泛型類型外,也可以在基類中包含泛型類型的聲明。包含泛型類型的聲明。 但基類如果是泛型類,它的類型要么已實例化,要但基類如果是泛型類,它的類型要么已實

20、例化,要么來源于子類(同樣是泛型類型)聲明的類型參數(shù)。么來源于子類(同樣是泛型類型)聲明的類型參數(shù)。例如,若聲明了如下泛型:例如,若聲明了如下泛型:class C則以下聲明是正確的:則以下聲明是正確的:class D:C/繼承的類型已實例化繼承的類型已實例化class E:C/E類型為類型為C類型提供了類型提供了U、V,即來源于子類,即來源于子類class F:C /F類型繼承于類型繼承于C,可看成,可看成F繼繼承一個非泛型的類承一個非泛型的類而以下聲明是錯誤的:而以下聲明是錯誤的:class G:C /因為因為G類型不是泛型,類型不是泛型,C是泛型,是泛型,G無法給無法給C提供泛提供泛型的實

21、例化型的實例化 7.1.6 7.1.6 泛型接口和委托泛型接口和委托1. 泛型接口泛型接口 與泛型繼承類似,泛型接口的類型參數(shù)要么已實例化,與泛型繼承類似,泛型接口的類型參數(shù)要么已實例化,要么來源于實現(xiàn)類聲明的類型參數(shù)。要么來源于實現(xiàn)類聲明的類型參數(shù)。 2. 泛型委托泛型委托 泛型委托支持在委托返回值和參數(shù)上應(yīng)用參數(shù)類型,泛型委托支持在委托返回值和參數(shù)上應(yīng)用參數(shù)類型,這些參數(shù)類型同樣可以附帶合法的約束。這些參數(shù)類型同樣可以附帶合法的約束。例如:例如:delegate bool MyDelegate(T value);class MyClass static bool method1(int i

22、) static bool method2(string s) static void Main() MyDelegate p2 = method2; MyDelegate p1 = new MyDelegate( method1); 反射是一種機制,通過這種機制可以知道一個未知類反射是一種機制,通過這種機制可以知道一個未知類型的類型信息。型的類型信息。例如有一個對象,它例如有一個對象,它不是我們定義的不是我們定義的,既可能是通過,既可能是通過網(wǎng)絡(luò)捕捉到的,也可能是使用泛型定義的,但我們網(wǎng)絡(luò)捕捉到的,也可能是使用泛型定義的,但我們想知道想知道這個對象的類型信息,想知道這個對象有哪些方法或者屬這

23、個對象的類型信息,想知道這個對象有哪些方法或者屬性什么性什么的,甚至的,甚至想進一步調(diào)用這個對象的方法想進一步調(diào)用這個對象的方法。關(guān)鍵是現(xiàn)。關(guān)鍵是現(xiàn)在只知道它是一個對象,不知道它的類型,自然不會知道在只知道它是一個對象,不知道它的類型,自然不會知道它有哪些方法等信息,這時該怎么辦呢它有哪些方法等信息,這時該怎么辦呢?7.2.1 7.2.1 反射概述反射概述反射機制就是解決這么一個問題的,通過反射機制就是解決這么一個問題的,通過反射機制就反射機制就可以知道未知類型對象的類型信息可以知道未知類型對象的類型信息。歸納歸納起來,反射在下列情況下很有用:起來,反射在下列情況下很有用:l 需要訪問程序元數(shù)

24、據(jù)的屬性。需要訪問程序元數(shù)據(jù)的屬性。l 檢查和實例化程序集中的類型。檢查和實例化程序集中的類型。l 在運行時構(gòu)建新類型。在運行時構(gòu)建新類型。l 執(zhí)行后期綁定,訪問在運行時創(chuàng)建的類型的方法。執(zhí)行后期綁定,訪問在運行時創(chuàng)建的類型的方法。1. Type類類System.Reflection是反射的命名空間,而是反射的命名空間,而Type類為類為System.Reflection功能的根,也是訪問元數(shù)據(jù)的主要方式。功能的根,也是訪問元數(shù)據(jù)的主要方式。Type類表示類型聲明,包括類類型、接口類型、數(shù)組類表示類型聲明,包括類類型、接口類型、數(shù)組類型、值類型、枚舉類型、類型參數(shù)、泛型類型定義,以類型、值類型

25、、枚舉類型、類型參數(shù)、泛型類型定義,以及開放或封閉構(gòu)造的泛型類型。及開放或封閉構(gòu)造的泛型類型。7.2.2 7.2.2 反射中常用的類反射中常用的類公共屬性公共屬性說明說明IsAbstract獲取一個值,通過該值指示獲取一個值,通過該值指示Type是否為抽象的并且必須被重寫是否為抽象的并且必須被重寫IsArray獲取一個值,通過該值指示獲取一個值,通過該值指示Type是否為數(shù)組是否為數(shù)組IsByRef獲取一個值,通過該值指示獲取一個值,通過該值指示Type是否由引用傳遞是否由引用傳遞IsClass獲取一個值,通過該值指示獲取一個值,通過該值指示Type是否是一個類,即不是值類型或接口是否是一個類

26、,即不是值類型或接口IsInterface獲取一個值,通過該值指示獲取一個值,通過該值指示Type是否為接口,即不是類或值類型是否為接口,即不是類或值類型IsSubclassOf確定當(dāng)前確定當(dāng)前Type表示的類是否是從指定的表示的類是否是從指定的Type表示的類派生的表示的類派生的MakeArrayType返回一個表示當(dāng)前類型的一維數(shù)組(下限為零)的返回一個表示當(dāng)前類型的一維數(shù)組(下限為零)的Type對象對象Module獲取在其中定義當(dāng)前獲取在其中定義當(dāng)前Type的模塊的模塊Name獲取當(dāng)前成員的名稱獲取當(dāng)前成員的名稱Namespace獲取獲取Type的命名空間的命名空間ReflectedTy

27、pe獲取用于獲取該成員的類對象獲取用于獲取該成員的類對象Type類的屬性類的屬性方法方法說明說明GetElementType當(dāng)在派生類中重寫時,返回當(dāng)前數(shù)組、指針或引用類型包含的或引用當(dāng)在派生類中重寫時,返回當(dāng)前數(shù)組、指針或引用類型包含的或引用的對象的的對象的TypeGetEvent獲取由當(dāng)前獲取由當(dāng)前Type聲明或繼承的特定事件聲明或繼承的特定事件GetEvents獲取由當(dāng)前獲取由當(dāng)前Type聲明或繼承的事件聲明或繼承的事件GetField獲取當(dāng)前獲取當(dāng)前Type的特定字段的特定字段GetFields獲取當(dāng)前獲取當(dāng)前Type的字段的字段GetInterface獲取由當(dāng)前獲取由當(dāng)前Type實現(xiàn)

28、或繼承的特定接口實現(xiàn)或繼承的特定接口GetInterfaces當(dāng)在派生類中重寫時,獲取由當(dāng)前當(dāng)在派生類中重寫時,獲取由當(dāng)前Type實現(xiàn)或繼承的所有接口實現(xiàn)或繼承的所有接口GetMember獲取當(dāng)前獲取當(dāng)前Type的指定成員的指定成員GetMembers獲取當(dāng)前獲取當(dāng)前Type的成員(包括屬性、方法、字段、事件等)的成員(包括屬性、方法、字段、事件等)GetMethod獲取當(dāng)前獲取當(dāng)前Type的特定方法的特定方法GetMethods獲取當(dāng)前獲取當(dāng)前Type的方法的方法GetProperties獲取當(dāng)前獲取當(dāng)前Type的屬性的屬性GetProperty獲取當(dāng)前獲取當(dāng)前Type的特定屬性的特定屬性I

29、nvokeMember使用指定的綁定約束并匹配指定的參數(shù)列表,調(diào)用指定成員使用指定的綁定約束并匹配指定的參數(shù)列表,調(diào)用指定成員Type類的方法類的方法歸納起來,得到一個歸納起來,得到一個Type實例的三種方法如下:實例的三種方法如下:(1)使用)使用System.Object.GetType(),例如:例如:Person pe=new Person();/定義定義pe為為person類的一個對象類的一個對象Type t=pe.GetType();這樣這樣t為為pe的的Type對象。對象。(2)使用)使用System.Type.GetType()靜態(tài)方法,靜態(tài)方法,參數(shù)為參數(shù)為類型的完全限定名。

30、例如:類型的完全限定名。例如:Type t=Type.GetType(MyNs.Person);其中,其中,MyNs.Person為為MyNs命名空間中的命名空間中的Person類,類,這樣這樣t為該類的為該類的Type對象。對象。(3)使用)使用typeof運算符運算符,例如:,例如:Type t=typeof(Person);其中其中Person為一個類,這樣為一個類,這樣t為該類的為該類的Type對象。對象。2. System.Reflection反射命名空間反射命名空間System.Reflection反射命名空間包含提供加載類型、方反射命名空間包含提供加載類型、方法和字段的有組織的視

31、圖的類和接口,具有動態(tài)創(chuàng)建和調(diào)法和字段的有組織的視圖的類和接口,具有動態(tài)創(chuàng)建和調(diào)用類型的功能。其中主要的類及其功能如下:用類型的功能。其中主要的類及其功能如下:l Assembly類:類:通過它可以加載、了解和操作一個程序集。通過它可以加載、了解和操作一個程序集。l AssemblyName類:類:通過它可以找到大量隱藏在程序集的身份通過它可以找到大量隱藏在程序集的身份中的信息,如版本信息、區(qū)域信息等。中的信息,如版本信息、區(qū)域信息等。l ConstructorInfo類:類:用于發(fā)現(xiàn)構(gòu)造函數(shù)及調(diào)用構(gòu)造函數(shù)。通用于發(fā)現(xiàn)構(gòu)造函數(shù)及調(diào)用構(gòu)造函數(shù)。通過對過對ConstructorInfo調(diào)用調(diào)用In

32、voke來創(chuàng)建對象,其中來創(chuàng)建對象,其中ConstructorInfo是由是由Type對象的對象的GetConstructors或或GetConstructor方法返回的。方法返回的。l EventInfo類:類:通過它可以找到事件的信息。通過它可以找到事件的信息。l FieldInfo類:類:通過它可以找到字段的信息。通過它可以找到字段的信息。l MethodInfo類:類:通過它可以找到方法的信息。通過它可以找到方法的信息。l ParameterInfo類:類:通過它可以找到參數(shù)的信息。通過它可以找到參數(shù)的信息。l PropertyInfo類:類:通過它可以找到屬性的信息。通過它可以找到屬

33、性的信息。l MemberInfo類:類:它是一個抽象基類,為它是一個抽象基類,為EventInfo、FieldInfo、MethodInfo、PropertyInfo等類型定義了公共的行為。等類型定義了公共的行為。l Module類:類:用來訪問帶有多文件程序集的給定模塊。用來訪問帶有多文件程序集的給定模塊。l DefaultMemberAttribute類:類:定義某類型的成員,該成員是定義某類型的成員,該成員是InvokeMember使用的默認(rèn)成員。使用的默認(rèn)成員。 公共屬性公共屬性說明說明EntryPoint獲取此程序集的入口點獲取此程序集的入口點FullName獲取程序集的顯示名稱獲

34、取程序集的顯示名稱Location獲取包含清單的已加載文件的路徑或位置獲取包含清單的已加載文件的路徑或位置ManifestModule獲取包含當(dāng)前程序集清單的模塊獲取包含當(dāng)前程序集清單的模塊其中其中重要的重要的Assembly類,它的常用屬性和常用方法如下。類,它的常用屬性和常用方法如下。Assembly類的常用屬性類的常用屬性 方法方法說明說明GetFiles獲取程序集清單文件表中的文件獲取程序集清單文件表中的文件GetModule獲取此程序集中的指定模塊獲取此程序集中的指定模塊GetModules獲取作為此程序集的一部分的所有模塊獲取作為此程序集的一部分的所有模塊GetType獲取表示指定

35、類型的獲取表示指定類型的Type對象對象GetTypes獲取此程序集中定義的類型獲取此程序集中定義的類型LoadFile加載程序集文件的內(nèi)容加載程序集文件的內(nèi)容LoadFrom在已知程序集的文件名或路徑等信息時加載程序集在已知程序集的文件名或路徑等信息時加載程序集LoadModule加載此程序集的內(nèi)部模塊加載此程序集的內(nèi)部模塊Assembly類的常用方法類的常用方法 1. 通過反射查看類型的成員信息通過反射查看類型的成員信息查看類型信息的過程如下:查看類型信息的過程如下:(1)獲取指定類型的一個)獲取指定類型的一個Type對象或?qū)ο蠡騎ype對象數(shù)組。對象數(shù)組。(2)通過)通過Type類的許多

36、方法來發(fā)現(xiàn)與該類型的成員有類的許多方法來發(fā)現(xiàn)與該類型的成員有關(guān)的信息。關(guān)的信息。7.2.3 7.2.3 反射的應(yīng)用示例反射的應(yīng)用示例【例例7.3】 編寫一個程序,通過反射輸出編寫一個程序,通過反射輸出System.Object類的方法、字段和構(gòu)造函數(shù)的信息。類的方法、字段和構(gòu)造函數(shù)的信息。解:解:先通過先通過Type的的GetTypes()方法獲取方法獲取System.Object類類的的Type對象對象t,然后用,然后用Type類的類的GetMethods()、GetFields()、GetConstructors()分別獲取分別獲取t對象的方法、字段和構(gòu)造函數(shù)信對象的方法、字段和構(gòu)造函數(shù)信

37、息并輸出。程序如下:息并輸出。程序如下:using System;using System.Reflection;namespace proj7_3class Programstatic void Main(string args) string classname = System.Object;Console.WriteLine(0類類,classname);Type t = Type.GetType(classname);MethodInfo m = t.GetMethods();Console.WriteLine( 0的方法個數(shù)的方法個數(shù):1, t.FullName, m.Length

38、);foreach(MethodInfo item in m) Console.WriteLine(t0 ,item.Name); FieldInfo f = t.GetFields(); Console.WriteLine( 0的字段個數(shù)的字段個數(shù):1, t.FullName, f.Length); foreach (FieldInfo item in f) Console.WriteLine(t0 , item.Name); ConstructorInfo c = t.GetConstructors();Console.WriteLine( 0的構(gòu)造函數(shù)個數(shù)的構(gòu)造函數(shù)個數(shù):1, t.Ful

39、lName, c.Length);foreach (ConstructorInfo item in c)Console.WriteLine(t0 , item.Name); 程序執(zhí)行結(jié)果程序執(zhí)行結(jié)果2. 通過反射調(diào)用未知類的某方法通過反射調(diào)用未知類的某方法調(diào)用未知類的某方法的過程如下:調(diào)用未知類的某方法的過程如下:(1)假設(shè)一個未知類)假設(shè)一個未知類c屬于某個屬于某個DLL文件文件xyz.dll,采,采用用Assembly.LoadFrom(xyz.dll)加載該程序集。加載該程序集。(2)調(diào)用)調(diào)用assembly.GetTypes()方法得到一個方法得到一個Type對對象數(shù)組象數(shù)組t。(3

40、)通過)通過Type.GetConstructor()方法得到某個對象方法得到某個對象的構(gòu)造函數(shù)。的構(gòu)造函數(shù)。(4)通過)通過ConstructorInfo.Invoke()方法調(diào)用構(gòu)造函方法調(diào)用構(gòu)造函數(shù)創(chuàng)建未知類的對象數(shù)創(chuàng)建未知類的對象s。(5)通過對象)通過對象s調(diào)用某方法。調(diào)用某方法?!纠?.4】 有一個項目有一個項目proj7_4,通過添加代碼文件模板,通過添加代碼文件模板向其中添加一個向其中添加一個Sport.cs文件,該文件的內(nèi)容如下:文件,該文件的內(nèi)容如下: using System;public abstract class Sport/體育運動類體育運動類protected

41、 string name; /項目名項目名public abstract string GetDuration();/獲取比賽時間獲取比賽時間public abstract string GetName();/獲取項目名獲取項目名 在命令行方式下使用以下命令生成在命令行方式下使用以下命令生成Sport.dll文件:文件:csc/target:library Sport.cs同樣通過添加代碼文件模板向其中添加一個同樣通過添加代碼文件模板向其中添加一個SomeSports.cs文件,該文件的內(nèi)容如下:文件,該文件的內(nèi)容如下:using System;public class Basketball

42、: Sport public Basketball()/籃球類籃球類 name = 籃球籃球; public override string GetDuration() return 共共4節(jié)節(jié),每,每節(jié)節(jié)15分鐘分鐘; public override string GetName() return name; public class Hockey : Sport/曲棍球類曲棍球類public Hockey()name = 曲棍球曲棍球; public override string GetDuration()return 兩個半場,兩個半場,各各35分鐘分鐘; public overrid

43、e string GetName()return name; public class Football : Sport/足球類足球類public Football()name = 足球足球; public override string GetDuration()return 兩個半場,兩個半場,各各45分鐘分鐘; public override string GetName()return name; 在命令行方式下使用以下命令生成在命令行方式下使用以下命令生成SomeSports.dll文件:文件:csc/target:library /reference:Sport.dll SomeSports.cs這樣就生成兩個動態(tài)鏈接庫文件這樣就生成兩個動態(tài)鏈接庫文件Sport.dll和和SomeSports.dll?,F(xiàn)要在現(xiàn)要在Prog

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論