C# 反射,動態編譯

反射是動態獲取程序集的元數據的一種技術,這句話是作.NET程序員面試題目的一個的答案,你可選擇記住它,就比如高中生物學裏面講到的細胞的結構的課程時,細胞由細胞膜,細胞質和細胞核組成。根據作程序的經驗,Never ask why不是好習慣,即便是微軟的API,有時候違反了調用約定,也會很抓狂。 

請看下面這一段代碼 
Assembly assembly = Assembly.GetExecutingAssembly();程序員

object entryForm = Activator.CreateInstance(formBaseType) as Form;面試

entryForm .MdiParent = this; 
entryForm .Show(); 
entryForm .Activate(); 
代碼的含義比較簡單,從當前程序集中建立formBaseType類型,並調用它的方法。從方法名上來看,大概能夠看出,這是一段MDI建立child子窗體,並顯示子窗體的代碼。 
這段小代碼,也是插件式框架的基本思路,請參考《Management Console 工具管理類軟件通用開發框架(開放源碼)》中的例子來體會它的用處。 
在ERP/MIS系統中,應用反射的例子,實在是太多了。數據訪問接口InventoryMovementDAL,藉助於反射,來查找並調用它的實現類; 窗體也它的子窗體藉助於反射來獲取屬性,傳遞值;ERP系統的整個框架,也是藉助於反射搭建起來. 

看下面的圖,ERP的三個模塊Paradox.ERP.SystemAdministration, Paradox.ERP.Engineering,Paradox.ERP.Inventory被Paradox.Framework.Kernal反射調用,若是再寫一個Paradox.ERP.Sales的銷售模塊,幾乎不須要改動,就能夠讓它被框架調用。框架

image 

動態編譯的例子,是應用到一個工資系統中. 請看圖 
imageide

對於如何解析工資的formular公式,有若干種辦法,這裏使有的是動態編譯的方法。把每個工資項當作是一個類型class的屬性,Formular的內容則放到一個方法中去,當成表達式計算求職,最後應用反射,返回各屬性的值便可。 
public class FormularCalculation 
    { 
        public static object Build(string[] items, string formular) 
        { 
            string nameSpace = "A"; 
            string className = "FormularCalculation"; 
            string methodName = "Run"; 
            CSharpCodeProvider compiler = new CSharpCodeProvider(); 
            CompilerParameters paras = new CompilerParameters(); 
            paras.GenerateExecutable = false; 
            paras.GenerateInMemory = true; 
            
           StringBuilder classSrc = new StringBuilder(); 
            classSrc.Append(" using  System;"+Environment.NewLine); 
            classSrc.Append(" namespace "+nameSpace+" { " + Environment.NewLine); 
            classSrc.Append("public  class  " + className + "{ " + Environment.NewLine); 
            foreach (string item in items) 
            { 
                classSrc.Append("public decimal " + item + ";" + Environment.NewLine); 
            } 
            classSrc.Append("public  void Run() { 基本工資=5000; " + Environment.NewLine); 
             string [] format= Regex.Split(formular,Environment.NewLine); 
             foreach (string prop in format) 
             { 
                 classSrc.Append(prop +" ;"+ Environment.NewLine); 
             } 
            classSrc.Append("}"+Environment.NewLine); 
            classSrc.Append("}" + Environment.NewLine); 
            classSrc.Append("}" + Environment.NewLine); 
            string source = classSrc.ToString(); 

            CompilerResults result = compiler.CompileAssemblyFromSource(paras, source); 
            CompilerErrorCollection error= result.Errors; 
            Assembly assembly = result.CompiledAssembly; 
            object eval = assembly.CreateInstance(nameSpace+"."+className); 
            MethodInfo method = eval.GetType().GetMethod(methodName); 
            object reobj = method.Invoke(eval, null); 
            return eval; 
        } 
    } 
調用方法以下 
string[] items = { "應發合計","基本工資","獎金","福利費", "扣款合計","社保","稅","實發合計","應稅所得額"}; 
string formular=@ 」    應發合計=基本工資+ 獎金 + 福利費 - 扣款合計; 
扣款合計=社保 + 稅+ 應稅所得額; 
實發合計=應發合計-  扣款合計; "; 
object obj = FormularCalculation.Build(items, formular); 
            Type type = obj.GetType(); 
            foreach (PropertyInfo fi in type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public 
                                               | BindingFlags.Instance | BindingFlags.DeclaredOnly)) 
            { 
                string value = fi.Name;  //取到計算後的各個屬性的值 
            } 
動態編譯還應用於軟件的加密,在內存中產生加密程序的源代碼,動態編譯並運行,檢測是否符合license受權。 工具

相關文章
相關標籤/搜索