詳解.NET中的代碼動(dòng)態(tài)編譯_.Net教程
推薦:.NET編程之關(guān)于VS 2008和.NET 3.5 Beta2新特性介紹非常重要的注意事項(xiàng): 請(qǐng)閱讀本博客貼子下面的“安裝注意事項(xiàng)”,內(nèi)含安裝之后你必要采取的幾個(gè)步驟,以保證一切運(yùn)行良好。其中一個(gè)步驟修正了并行安裝造成的ASP.NET AJAX問題。
代碼的動(dòng)態(tài)編譯并執(zhí)行是一個(gè).NET平臺(tái)提供給我們的很強(qiáng)大的工具用以靈活擴(kuò)展(當(dāng)然是面對(duì)內(nèi)部開發(fā)人員)復(fù)雜而無法估算的邏輯,并通過一些額外的代碼來擴(kuò)展我們已有的應(yīng)用程序。這在很大程度上給我們提供了另外一種擴(kuò)展的方式(當(dāng)然這并不能算是嚴(yán)格意義上的擴(kuò)展,但至少為我們提供了一種思路)。
動(dòng)態(tài)代碼執(zhí)行可以應(yīng)用在諸如模板生成,外加邏輯擴(kuò)展等一些場(chǎng)合。一個(gè)簡(jiǎn)單的例子,為了網(wǎng)站那的響應(yīng)速度,HTML靜態(tài)頁面往往是我們最好的選擇,但基于數(shù)據(jù)驅(qū)動(dòng)的網(wǎng)站往往又很難用靜態(tài)頁面實(shí)現(xiàn),那么將動(dòng)態(tài)頁面生成html的工作或許就是一個(gè)很好的應(yīng)用場(chǎng)合。另外,對(duì)于一些模板的套用,我們同樣可以用它來做。另外這本身也是插件編寫的方式。
最基本的動(dòng)態(tài)編譯
.Net為我們提供了很強(qiáng)大的支持來實(shí)現(xiàn)這一切我們可以去做的基礎(chǔ),主要應(yīng)用的兩個(gè)命名空間是:System.CodeDom.Compiler和Microsoft.CSharp或Microsoft.VisualBasic。另外還需要用到反射來動(dòng)態(tài)執(zhí)行你的代碼。動(dòng)態(tài)編譯并執(zhí)行代碼的原理其實(shí)在于將提供的源代碼交予CSharpCodeProvider來執(zhí)行編譯(其實(shí)和CSC沒什么兩樣),如果沒有任何編譯錯(cuò)誤,生成的IL代碼會(huì)被編譯成DLL存放于于內(nèi)存并加載在某個(gè)應(yīng)用程序域(默認(rèn)為當(dāng)前)內(nèi)并通過反射的方式來調(diào)用其某個(gè)方法或者觸發(fā)某個(gè)事件等。之所以說它是插件編寫的一種方式也正是因?yàn)榕c此,我們可以通過預(yù)先定義好的借口來組織和擴(kuò)展我們的程序并將其交還給主程序去觸發(fā)。一個(gè)基本的動(dòng)態(tài)編譯并執(zhí)行代碼的步驟包括:
·將要被編譯和執(zhí)行的代碼讀入并以字符串方式保存
·聲明CSharpCodeProvider對(duì)象實(shí)例
·調(diào)用CSharpCodeProvider實(shí)例的CompileAssemblyFromSource方法編譯
·用反射生成被生成對(duì)象的實(shí)例(Assembly.CreateInstance)
·調(diào)用其方法
以下代碼片段包含了完整的編譯和執(zhí)行過程:
需要解釋的是,這里我們?cè)趥鬟f編譯參數(shù)時(shí)設(shè)置了GenerateInMemory為true,這表明生成的DLL會(huì)被加載在內(nèi)存中(隨后被默認(rèn)引用入當(dāng)前應(yīng)用程序域)。在調(diào)用GetTime方法時(shí)我們需要加入?yún)?shù),傳遞object類型的數(shù)組并通過Reflection的InvokeMember來調(diào)用。在創(chuàng)建生成的Assembly中的對(duì)象實(shí)例時(shí),需要注意用到的命名空間是你輸入代碼的真實(shí)命名空間。以下是我們輸入的測(cè)試代碼(為了方便,所有的代碼都在外部輸入,動(dòng)態(tài)執(zhí)行時(shí)不做調(diào)整):
運(yùn)行附件中提供的程序,可以很容易得到一下結(jié)果:

改進(jìn)的執(zhí)行過程
現(xiàn)在一切看起來很好,我們可以編譯代碼并把代碼加載到當(dāng)前應(yīng)用程序域中來參與我們的活動(dòng),但你是否想過去卸載掉這段程序呢?更好的去控制程序呢?另外,當(dāng)你運(yùn)行這個(gè)程序很多遍的時(shí)候,你會(huì)發(fā)現(xiàn)占用內(nèi)存很大,而且每次執(zhí)行都會(huì)增大內(nèi)存使用。是否需要來解決這個(gè)問題呢?當(dāng)然需要,否則你會(huì)發(fā)現(xiàn)這個(gè)東西根本沒用,我需要執(zhí)行的一些大的應(yīng)用會(huì)讓我的服務(wù)器crzay,不堪重負(fù)而瘋掉的。
要解決這個(gè)問題我們需要來了解一下應(yīng)用程序域。.NET Application Domain是.NET提供的運(yùn)行和承載一個(gè)活動(dòng)的進(jìn)程(Process)的容器,它將這個(gè)進(jìn)程運(yùn)行所需的代碼和數(shù)據(jù),隔離到一個(gè)小的范圍內(nèi),稱為Application Domain。當(dāng)一個(gè)應(yīng)用程序運(yùn)行時(shí),Application Domains將所有的程序集/組件集加載到當(dāng)前的應(yīng)用程序域中,并根據(jù)需要來調(diào)用。而對(duì)于動(dòng)態(tài)生成的代碼/程序集,我們看起來好像并沒有辦法去管理它。其實(shí)不然,我們可以用Application Domain提供的管理程序集的辦法來動(dòng)態(tài)加載和移除Assemblies來達(dá)到我們的提高性能的目的。具體怎么做呢,在前邊的基礎(chǔ)上增加以下步驟:
·創(chuàng)建另外一個(gè)Application Domain
·動(dòng)態(tài)創(chuàng)建(編譯)代碼并保存到磁盤
·創(chuàng)建一個(gè)公共的遠(yuǎn)程調(diào)用接口
·創(chuàng)建遠(yuǎn)程調(diào)用接口的實(shí)例。并通過這個(gè)接口來訪問其方法。
換句話來講就是將對(duì)象加載到另外一個(gè)AppDomain中并通過遠(yuǎn)程調(diào)用的方法來調(diào)用。所謂遠(yuǎn)程調(diào)用其實(shí)也就是跨應(yīng)用程序域調(diào)用,所以這個(gè)對(duì)象(動(dòng)態(tài)代碼)必須繼承于MarshalByRefObject類。為了復(fù)用,這個(gè)接口被單獨(dú)提到一個(gè)工程中,并提供一個(gè)工廠來簡(jiǎn)化每次的調(diào)用操作:
接下來在原來基礎(chǔ)上需要修改的是:
·將編譯成的DLL保存到磁盤中。
·創(chuàng)建另外的AppDomain。
·獲得IRemoteInterface接口的引用。(將生成的DLL加載到額外的AppDomain)
·調(diào)用InvokeMethod方法來遠(yuǎn)程調(diào)用。
·可以通過AppDomain.Unload()方法卸載程序集。
以下是完整的代碼,演示了如何應(yīng)用這一方案。
對(duì)于客戶端的輸入程序,我們需要繼承于MarshalByRefObject類和IRemoteInterface接口,并添加對(duì)RemoteAccess程序集的引用。以下為輸入:
這樣,你可以通過適時(shí)的編譯,加載和卸載程序集來保證你的程序始終處于一個(gè)可控消耗的過程,并且達(dá)到了動(dòng)態(tài)編譯的目的,而且因?yàn)樵诓煌膽?yīng)用程序域中,讓你的本身的程序更加安全和健壯。
分享:揭秘ASP.NET實(shí)現(xiàn)頁面間值傳遞的幾種方法第一種方法: 通過URL鏈接地址傳遞 以下為引用的內(nèi)容: send.aspx: protected void Button1_Click(object sende
- asp.net如何得到GRIDVIEW中某行某列值的方法
- .net SMTP發(fā)送Email實(shí)例(可帶附件)
- js實(shí)現(xiàn)廣告漂浮效果的小例子
- asp.net Repeater 數(shù)據(jù)綁定的具體實(shí)現(xiàn)
- Asp.Net 無刷新文件上傳并顯示進(jìn)度條的實(shí)現(xiàn)方法及思路
- Asp.net獲取客戶端IP常見代碼存在的偽造IP問題探討
- VS2010 水晶報(bào)表的使用方法
- ASP.NET中操作SQL數(shù)據(jù)庫(連接字符串的配置及獲取)
- asp.net頁面?zhèn)髦禍y(cè)試實(shí)例代碼
- DataGridView - DataGridViewCheckBoxCell的使用介紹
- asp.net中javascript的引用(直接引入和間接引入)
- 三層+存儲(chǔ)過程實(shí)現(xiàn)分頁示例代碼
.Net教程Rss訂閱編程教程搜索
.Net教程推薦
- GridView/DataGrid行單擊和雙擊事件實(shí)現(xiàn)代碼
- 基于.NET中建構(gòu)子中傳遞子對(duì)象的對(duì)象詳解
- .NET 線程基礎(chǔ)的使用介紹
- asp.net中使用repeater和PageDataSource搭配實(shí)現(xiàn)分頁代碼
- 七招制勝ASP.NET應(yīng)用程序開發(fā)
- ASP.NET中9條應(yīng)該遵守的代碼編寫規(guī)范
- c# 連接字符串?dāng)?shù)據(jù)庫服務(wù)器端口號(hào)
- 解析Asp.Net頁面執(zhí)行流程
- ASP.NET2.0服務(wù)器控件之創(chuàng)建復(fù)雜屬性
- 揭秘設(shè)計(jì)ASP.NET應(yīng)用程序的七大妙招
- 相關(guān)鏈接:
- 教程說明:
.Net教程-詳解.NET中的代碼動(dòng)態(tài)編譯
。