[C#]C#學(xué)習(xí)筆記-CIL和動態(tài)程序集
C#學(xué)習(xí)筆記-CIL和動態(tài)程序集
羅朝輝(http://www.rzrgm.cn/kesalin/)
《C#與.NET高級程序設(shè)計(jì)》讀書筆記
1,System.Reflection.Emit 命名空間提供了很多在運(yùn)行時能夠在內(nèi)存中產(chǎn)生.NET程序集的類型,在內(nèi)存中定義和執(zhí)行程序集的正式術(shù)語是動態(tài)程序集(dynamic assembly)。我們使用專有的 CIL(公共中間語言)指令集來動態(tài)構(gòu)建程序集。
2,CIL 本質(zhì)上就是.NET平臺的母語,當(dāng)我們選擇某種托管的編程語言(C#,VB,COBOL.NET等)構(gòu)建.NET程序集時,同這個語言相關(guān)的編譯器就會把源代碼翻譯成CIL。我們可以直接使用.NET Framework SDK提供的 CIL 和 CIL編譯器(ilasm.exe)來開發(fā)和構(gòu)建.NET程序集,雖然通常我們很少這么做。這么說把CIL對應(yīng).NET開發(fā)人員就好比匯編語言對于一個C++程序員一樣。
3,CIL定義了一組通用的關(guān)鍵字,這些關(guān)鍵字可以分為三個類別:CIL指令,CIL特性和CIL操作碼。
CIL指令用于描述.NET程序集總體結(jié)構(gòu),它用于通知CIL編譯器如何定義在程序集用到的命名空間,類型和成員。CIL指令語法上使用一個(.)的前綴來表示,如:.namespace, .class, .publickeytoken, .method, .assembly等。
CIL特性可以限定應(yīng)該如何處理一個 CIL 指令。例如:一個.class指令可以同public特性(明確類的可見性),extends特性(明確類的基類)和 implements特性(明確類支持的接口)相結(jié)合。
CIL操作碼提供類的實(shí)現(xiàn)邏輯。如:ldstr(轉(zhuǎn)載字符串),box,unbox,throw,sizeof等。
4,CIL是一個完全以棧為基礎(chǔ)的開發(fā)語言,在CIL中用來負(fù)責(zé)這個棧實(shí)現(xiàn)的部分叫做虛擬執(zhí)行棧。將操作碼壓入這個棧的過程叫做加載(Load),將操作碼從棧頂移到內(nèi)存中(如局部變量)的過程叫做存儲(store)。 CIL不允許直接訪問一個數(shù)據(jù),包括局部變量,方法中傳入的變量或者類型的字段數(shù)據(jù)。為了實(shí)現(xiàn)訪問,必須顯式地加載數(shù)據(jù)到棧中,并在使用時彈出。
5,正反向工程:可以使用ildasm.exe將程序集的CIL代碼導(dǎo)出到外部文件,有了CIL代碼也可以使用CIL編譯器ilasm.exe重新編譯。正反向工程讓我們能夠修改一個沒有源代碼的程序集,也可以補(bǔ)充可與COM互操作的程序集在在裝換過程中丟失的IDL特性。
6,動態(tài)程序集在運(yùn)行中通過使用 System.Reflection.Emit命名空間提供的類型在內(nèi)存中創(chuàng)建,System.Reflection.Emit 命名空間使得在運(yùn)行時創(chuàng)建程序集及其模塊,類型定義以及CIL實(shí)現(xiàn)邏輯成為可能。一旦完成了這些,就可以將內(nèi)存中的二進(jìn)制程序保存到磁盤上生成一個新的靜態(tài)程序集。盡管創(chuàng)建動態(tài)程序集不是很常見,但在如下一些場合這個技術(shù)還是非常有用:第一,構(gòu)建需要根據(jù)用戶的輸入來生成程序集文件的.NET開發(fā)工具;第二,構(gòu)建需要在運(yùn)行時通過元數(shù)據(jù)來生成遠(yuǎn)程類型的代理的程序;第三,希望加載靜態(tài)程序集并能夠動態(tài)地插入新的類型到二進(jìn)制鏡像中。
浙公網(wǎng)安備 33010602011771號