c#銳利體驗
南京郵電學院李建忠(
lijianzhong@263.***.**)
第十六講對映
動態型別查詢
我們知道,
c#編譯後的
pe檔案主要由
il**和元資料組成,元資料為
.***
元件提供了豐富的自描述特性,它使得我們可以在**執行時獲知元件中的型別等重要的資訊。在
c#中這是通過一種稱作對映(
reflection
)的機制來完成的。先來看乙個示例,我們首先建立乙個簡單的型別:
// ******type.cs
public class myclass
set}
public void print()
}用編譯命令
csc /t:library ******type.cs
編譯上面的檔案得到
******type.dll
輸出。我們再來實現查詢型別的測試程式:
//test.cs
using system;
using system.reflection;
class test
",t.name);//
獲取型別的名字
fieldinfo fiarr=t.getfields();//
獲取所有的共有域
console.write("the fields :",fiarr.length);
foreach(fieldinfo o in fiarr)
console.writeline();
propertyinfo piarr=t.getproperties();//
獲取所有的公有屬性
console.write("the properties :",piarr.length);
foreach(propertyinfo o in piarr)
console.writeline();
methodinfo miarr=t.getmethods();//
獲取所有的公有方法
console.write("the methods :",miarr.length);
foreach(methodinfo o in miarr)}}
用編譯命令
csc /r:******type.dll test.cs
編譯後,執行可得到下面的輸出:
the type name : myclass
the 0 fields :
the 1 properties :count
the 7 methods :gethashcode equals tostring get_count set_count print gettype
在上面的例子中,我們首先通過
typeof(myclass)
獲得類myclass
的型別資訊,當然我們也可以通過建立物件例項,然後呼叫物件例項的
gettype
方法來獲得(每個類都從
object
根類中繼承獲得此方法)。在擁有了型別資訊(變數
t)後,我們便可以獲得其型別的名字,該型別含有的公有域,公有屬性,公有方法。注意這裡
c#的對映機制只允許我們獲取型別的公有資訊,這符合物件導向的封裝的原則。這也是為什麼我們雖然我們實現了
count
域,查詢型別得到的輸出卻是
「the 0 fields :」——
如果將******type.cs
中的count
域改為public
公有,我們將會得到他的查詢資訊。其中
4個方法(
gethashcode equals tostring gettype
)都是繼承自
object
類的公有方法,而方法
get_count
和set_count
則是我們在實現
count
屬性的「
副產物」——
這符合我們前面講述的屬性本質上為方法的變體。實際上,
system.type
類各種各樣的成員使得我們能夠獲得幾乎所有的與型別相關的公有資訊。在
system.reflection
命名空間下的各個類更是可以獲得各個程式設計元素更較詳細的資訊,如方法的引數與返回值,域的型別,列舉的各個值等。
動態建立與呼叫
實際上對映還遠遠不止於動態地獲知元件的型別資訊,它還能使我們在獲得型別資訊的基礎上,在**執行時進行型別的動態建立與方法的動態呼叫,甚至於動態地建立並執行
il**!
動態呼叫為
c#的元件提供了晚繫結功能,它使得元件之間在執行時的整合變得極為方便!利用前面建立的簡單的元件
******type.dll
,我們來看一看怎樣完成物件的動態建立和方法的動態呼叫:
// dynamicexe.cs
using system;
using system.reflection;
class test
, return :",mi.name,re);}}
}}}}
用編譯命令
csc /r:******type.dll dynamicexe.cs
編譯後,執行可得到下面的輸出:
gethashcode , return :8
tostring , return :myclass
get_count , return :100
100print , return :
gettype , return :myclass
我們在上面的例子給出了被動態呼叫的方法的名字和返回值。其中輸出的第4行為
100,它是我們動態呼叫方法
myclass.print()
的輸出。需要指出的是我們通過一定的控制,僅僅呼叫的是型別的公有的無引數的例項方法。給出元件的名字,運用
assembly.loadfrom
我們便可以動態的裝載元件。
activator.createinstance
允許動態地建立型別(我們這裡只通過無參的構造器來建立),實際上用它建立出來的型別和我們用
myclass o=new myclass()
建立出來的型別一模一樣。進而,我們便可以在查詢到的成員的基礎上,對它們進行動態呼叫。
microsoft.***
從底層的元資料設計入手,為對映機制提供了非常堅實的基礎。命名空間
system.reflection
和system.reflection.emit
為操作這種對映提供了實實在在的強大的
api程式設計介面,大大改善了元件的設計環境,提高了元件的互動能力!
C 銳利體驗 第十七講 異常處理
c 銳利體驗 南京郵電學院李建忠 lijianzhong 263.第十七講異常處理 異常處理 結構化異常處理是現代分布式環境下元件設計的乙個必要的環節,通用語言執行時從底層構造給予異常處理以堅實的支援。在c 中,異常物件被設計為封裝了各種異常資訊的類 system.exception及其繼承子類,和...
C 銳利體驗 第十講 介面 繼承與多型
第十講 介面 繼承與多型 介面 介面定義物件成員的合同,是現代元件程式設計不可缺少的一環。c 採用關鍵字 inte ce 來建立介面。介面作為一種型別,它也具有其他型別所共有的五種訪問修飾和new重定義修飾符。介面可以包含方法,屬性,事件,索引器四種成員,介面本身只能宣告這些成員,不必也不能提供這些...
第十六講 模板方法模式
template method模式也叫模板方法模式,是行為模式之一,它把具有特定步驟演算法中的某些必要的處理委讓給抽象方法,通過子類繼承對抽象方法的不同實現改變整個演算法的行為。template method模式一般應用在具有以下條件的應用中 package test.com.templatemet...