熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

詳解.NET中的動態編譯技術

2013-11-13 10:26:29  來源: .NET編程 

  代碼的動態編譯並執行是一個NET平台提供給我們的很強大的工具用以靈活擴展(當然是面對內部開發人員)復雜而無法估算的邏輯並通過一些額外的代碼來擴展我們已有 的應用程序這在很大程度上給我們提供了另外一種擴展的方式(當然這並不能算是嚴格意義上的擴展但至少為我們提供了一種思路)
 
  動態代碼執行可以應用在諸如模板生成外加邏輯擴展等一些場合一個簡單的例子為了網站那的響應速度HTML靜態頁面往往是我們最好的選擇但基於數據驅動的網站往往又很難用靜態頁面實現那麼將動態頁面生成html的工作或許就是一個很好的應用場合另外對於一些模板的套用我們同樣可以用它來做另外這本身也是插件編寫的方式

  最基本的動態編譯

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

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

  · 聲明CSharpCodeProvider對象實例

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

  · 用反射生成被生成對象的實例(AssemblyCreateInstance)

  · 調用其方法

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

  //get the code to compile string strSourceCode = thistxtSourceText; // Create a new CSharpCodePrivoder instance CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider(); // Sets the runtime compiling parameters

  by crating a new CompilerParameters instance CompilerParameters objCompilerParameters = new CompilerParameters(); objCompilerParametersReferencedAssembliesAdd(Systemdll); objCompilerParametersReferencedAssembliesAdd(SystemWindowsFormsdll); objCompilerParametersGenerateInMemory = true; // CompilerResults: Complile the code snippet

  by calling a method from the provider CompilerResults cr = objCSharpCodePrivoder

  CompileAssemblyFromSource(objCompilerParameters

  strSourceCode); if (crErrorsHasErrors) { string strErrorMsg = crErrorsCountToString() + Errors:; for (int x = ; x < crErrorsCount; x++) { strErrorMsg = strErrorMsg + \r\nLine: + crErrors[x]LineToString() + + crErrors[x]ErrorText; } thistxtResultText = strErrorMsg; MessageBoxShow(There were build erros please modify your code

  Compiling Error); return; } // Invoke the method by using Reflection Assembly objAssembly = crCompiledAssembly; object objClass = objAssemblyCreateInstance(DynamiclyHelloWorld); if (objClass == null) { thistxtResultText = Error: + Couldnt load class; return; } object[] objCodeParms = new object[]; objCodeParms[] = Allan; string strResult = (string)objClassGetType()InvokeMember( GetTime BindingFlagsInvokeMethod null objClass objCodeParms); thistxtResultText = strResult;

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

  using System; namespace Dynamicly { public class HelloWorld { public string GetTime(string strName) { return Welcome + strName +

  Check in at + SystemDateTimeNowToString(); } } }

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

  .NET編程免費提供,內容來源於互聯網,本文歸原作者所有。

推薦文章
Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.