国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

詳解.NET中的代碼動態編譯_.Net教程

2024-07-10 12:51:35
字體:
來源:轉載
供稿:網友

推薦:.NET編程之關于VS 2008和.NET 3.5 Beta2新特性介紹
非常重要的注意事項: 請閱讀本博客貼子下面的“安裝注意事項”,內含安裝之后你必要采取的幾個步驟,以保證一切運行良好。其中一個步驟修正了并行安裝造成的ASP.NET AJAX問題。

代碼的動態編譯并執行是一個.NET平臺提供給我們的很強大的工具用以靈活擴展(當然是面對內部開發人員)復雜而無法估算的邏輯,并通過一些額外的代碼來擴展我們已有的應用程序。這在很大程度上給我們提供了另外一種擴展的方式(當然這并不能算是嚴格意義上的擴展,但至少為我們提供了一種思路)。

動態代碼執行可以應用在諸如模板生成,外加邏輯擴展等一些場合。一個簡單的例子,為了網站那的響應速度,HTML靜態頁面往往是我們最好的選擇,但基于數據驅動的網站往往又很難用靜態頁面實現,那么將動態頁面生成html的工作或許就是一個很好的應用場合。另外,對于一些模板的套用,我們同樣可以用它來做。另外這本身也是插件編寫的方式。

最基本的動態編譯

.Net為我們提供了很強大的支持來實現這一切我們可以去做的基礎,主要應用的兩個命名空間是:System.CodeDom.Compiler和Microsoft.CSharp或Microsoft.VisualBasic。另外還需要用到反射來動態執行你的代碼。動態編譯并執行代碼的原理其實在于將提供的源代碼交予CSharpCodeProvider來執行編譯(其實和CSC沒什么兩樣),如果沒有任何編譯錯誤,生成的IL代碼會被編譯成DLL存放于于內存并加載在某個應用程序域(默認為當前)內并通過反射的方式來調用其某個方法或者觸發某個事件等。之所以說它是插件編寫的一種方式也正是因為與此,我們可以通過預先定義好的借口來組織和擴展我們的程序并將其交還給主程序去觸發。一個基本的動態編譯并執行代碼的步驟包括:

·將要被編譯和執行的代碼讀入并以字符串方式保存

·聲明CSharpCodeProvider對象實例

·調用CSharpCodeProvider實例的CompileAssemblyFromSource方法編譯

·用反射生成被生成對象的實例(Assembly.CreateInstance)

·調用其方法

以下代碼片段包含了完整的編譯和執行過程:

需要解釋的是,這里我們在傳遞編譯參數時設置了GenerateInMemory為true,這表明生成的DLL會被加載在內存中(隨后被默認引用入當前應用程序域)。在調用GetTime方法時我們需要加入參數,傳遞object類型的數組并通過Reflection的InvokeMember來調用。在創建生成的Assembly中的對象實例時,需要注意用到的命名空間是你輸入代碼的真實命名空間。以下是我們輸入的測試代碼(為了方便,所有的代碼都在外部輸入,動態執行時不做調整):

運行附件中提供的程序,可以很容易得到一下結果:

改進的執行過程
現在一切看起來很好,我們可以編譯代碼并把代碼加載到當前應用程序域中來參與我們的活動,但你是否想過去卸載掉這段程序呢?更好的去控制程序呢?另外,當你運行這個程序很多遍的時候,你會發現占用內存很大,而且每次執行都會增大內存使用。是否需要來解決這個問題呢?當然需要,否則你會發現這個東西根本沒用,我需要執行的一些大的應用會讓我的服務器crzay,不堪重負而瘋掉的。

要解決這個問題我們需要來了解一下應用程序域。.NET Application Domain是.NET提供的運行和承載一個活動的進程(Process)的容器,它將這個進程運行所需的代碼和數據,隔離到一個小的范圍內,稱為Application Domain。當一個應用程序運行時,Application Domains將所有的程序集/組件集加載到當前的應用程序域中,并根據需要來調用。而對于動態生成的代碼/程序集,我們看起來好像并沒有辦法去管理它。其實不然,我們可以用Application Domain提供的管理程序集的辦法來動態加載和移除Assemblies來達到我們的提高性能的目的。具體怎么做呢,在前邊的基礎上增加以下步驟:

·創建另外一個Application Domain

·動態創建(編譯)代碼并保存到磁盤

·創建一個公共的遠程調用接口

·創建遠程調用接口的實例。并通過這個接口來訪問其方法。

換句話來講就是將對象加載到另外一個AppDomain中并通過遠程調用的方法來調用。所謂遠程調用其實也就是跨應用程序域調用,所以這個對象(動態代碼)必須繼承于MarshalByRefObject類。為了復用,這個接口被單獨提到一個工程中,并提供一個工廠來簡化每次的調用操作:

接下來在原來基礎上需要修改的是:

·將編譯成的DLL保存到磁盤中。

·創建另外的AppDomain。

·獲得IRemoteInterface接口的引用。(將生成的DLL加載到額外的AppDomain)

·調用InvokeMethod方法來遠程調用。

·可以通過AppDomain.Unload()方法卸載程序集。

以下是完整的代碼,演示了如何應用這一方案。

對于客戶端的輸入程序,我們需要繼承于MarshalByRefObject類和IRemoteInterface接口,并添加對RemoteAccess程序集的引用。以下為輸入:

這樣,你可以通過適時的編譯,加載和卸載程序集來保證你的程序始終處于一個可控消耗的過程,并且達到了動態編譯的目的,而且因為在不同的應用程序域中,讓你的本身的程序更加安全和健壯。

分享:揭秘ASP.NET實現頁面間值傳遞的幾種方法
第一種方法:通過URL鏈接地址傳遞 以下為引用的內容: send.aspx: protected void Button1_Click(object sende

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平利县| 革吉县| 鸡泽县| 仙桃市| 莫力| 东海县| 连州市| 南宁市| 罗山县| 泽普县| 油尖旺区| 沽源县| 泽普县| 潼南县| 开远市| 邵阳县| 兖州市| 沈阳市| 乌鲁木齐市| 长岛县| 兰考县| 嘉义县| 淮滨县| 霍城县| 嘉荫县| 龙游县| 五河县| 泊头市| 探索| 绥德县| 海口市| 上饶县| 西乌珠穆沁旗| 嘉峪关市| 冷水江市| 靖州| 三台县| 钟祥市| 鸡泽县| 望江县| 永定县|