2012年10月11日 星期四

.NET 動態程式碼的產生與編譯(一)-簡述



        由於工作上的需要,必須讓產品程式在RunTime階段,「可隨機載入可外部修改的部份編碼程式」;例如某產品的輸出結果,依需求在RunTime會有不同的邏輯運算組合方式—複雜點甚至不同的演算法邏輯的搭配組合,並且不希望為了部份程式碼的修改重新編譯整個程式。所以,針對此需求大概可分成幾個部份的問題概念:
1.          如何動態編碼與組譯?
2.          若要動態編譯的程式碼只是部份碼(會利用到DesignTime階段已建立的方法與成員),那要如何解決呢?
3.          動態程式碼編譯完成後,如何載入到主程式中?

綜合以上需求,其實就是在使用CodeDOM這個Namespace,其主要用來表示程式碼中的項目和結構的相關類別。

以下擷取自MSDN
The .NET Framework includes a mechanism called the Code Document Object Model (CodeDOM) that enables developers of programs that emit source code to generate source code in multiple programming languages at run time, based on a single model that represents the code to render.
To represent source code, CodeDOM elements are linked to each other to form a data structure known as a CodeDOM graph, which models the structure of some source code.
The System.CodeDom namespace defines types that can represent the logical structure of source code, independent of a specific programming language. The System.CodeDom.Compiler namespace defines types for generating source code from CodeDOM graphs and managing the compilation of source code in supported languages. Compiler vendors or developers can extend the set of supported languages.
Language-independent source code modeling can be valuable when a program needs to generate source code for a program model in multiple languages or for an uncertain target language. For example, some designers use the CodeDOM as a language abstraction interface to produce source code in the correct programming language, if CodeDOM support for the language is available.
The .NET Framework includes code generators and code compilers for C#, JScript, and Visual Basic.
         
MSN的敘述中我們可以看出,CodeDOM提供了我們外部源碼在RunTime階段的生成與編譯功能,而其強大的CodeDom名稱空間包含了許多以語言中立的形式描述常見程式結構的物件,其中每一種語言的細節則由與該種語言對應的 CodeProvider物件負責處理。簡單講其包括了兩個主要部份:
1.          System.CodeDom讓程式自行產生一個通用程式語言的虛擬架構,例如CodeCompileUnit是用來為CodeDom程式容器提供容器,CodeEntryPointMethod則提供程式的進入點(eg. Main(){….}
2.          System.CodeDom.Complier則提供生成實際文檔,並提供編譯相關的功能,例如CodeDomProvider提供基底類別 (Base Class) 以轉換成其他語言eg. C#Microsoft.CSharp.CSharpCodeProvider)。

所以CodeDom基本上就可以解決源碼動態生成與編譯的問題;那要「動態程式碼編譯完成後,如何載入到主程式中?」的問題呢?這裡我們會用到.NET另外一個特別的技巧「反映 (Reflection)」,在下列狀況中,十分有利於Reflection的使用(節錄自MSDN:
·         當您需要存取程式中繼資料的屬性。請參閱使用反映存取屬性主題。
·         檢查與執行個體化組件中的型別。
·         在執行階段建置新型別。請使用 System.Reflection.Emit 中的類別。
·         執行晚期繫結,存取在執行階段所建立型別的方法。請參閱主題動態載入和使用型別

Reflection的概念很繁雜,在這裡其實主要只有MethodInfo的調用而已,等之後用到的時候再來細談。

沒有留言:

張貼留言