前不久看了一個C#菜鳥級工具 功能是在form寫代碼,重新編譯在Console裡執行
當時覺得這東西很新穎,就下載下來看看,沒想到坑爹的竟然是F#語言寫的,會函數式語言有幾個菜鳥啊啊啊啊- -
本著好奇精神,也為了在每月開會能有什麼東西能講,於是自己在網上找了點資料自己寫了一個,運行圖如下
OK,程式本身很簡單,在Console基礎上new一個form,然後form的button事件則是調用Console方法然後重編譯這段代碼執行
以下是建構函式裡拼接代碼的部分。
/// <summary> /// 解析字串建構函式 /// </summary> /// <param name="items">待解析字串數組</param> private void ConstructEvaluator(EvaluatorItem[] items) { //建立C#編譯器執行個體 ICodeCompiler comp = (new CSharpCodeProvider().CreateCompiler()); //編譯器的傳入參數 CompilerParameters cp = new CompilerParameters(); cp.ReferencedAssemblies.Add("system.dll"); //添加程式集 system.dll 的引用 cp.ReferencedAssemblies.Add("system.data.dll"); //添加程式集 system.data.dll 的引用 cp.ReferencedAssemblies.Add("system.xml.dll"); //添加程式集 system.xml.dll 的引用 cp.GenerateExecutable = false; //不產生可執行檔 cp.GenerateInMemory = true; //在記憶體中運行 StringBuilder code = new StringBuilder(); //建立代碼串 /* * 添加常見且必須的引用字串 */ code.Append("using System; \n"); code.Append("using System.Data; \n"); //code.Append("using System.Data.SqlClient; \n"); //code.Append("using System.Data.OleDb; \n"); //code.Append("using System.Xml; \n"); code.Append("namespace EvalGuy { \n"); //產生代碼的命名空間為EvalGuy,和本代碼一樣 code.Append(" public class _Evaluator { \n"); //產生 _Evaluator 類,所有可執行代碼均在此類中運行 foreach (EvaluatorItem item in items) //遍曆每一個可執行字串項 { code.AppendFormat(" public {0} {1}() ", //添加定義公用函數代碼 item.ReturnType.Name, //函數傳回值為可執行字串項中定義的傳回值類型 item.Name); //函數名稱為可執行字串項中定義的執行字串名稱 code.Append("{\n"); //添加函數開始括弧 string[] strs = item.Expression.Split(';'); code.Append("object obj=\"\";\n"); code.Append("try{\n"); foreach (string s in strs) { code.Append(s + ";\n"); } code.Append("}\n catch{}\n"); code.Append("return obj;"); code.Append("}\n"); //添加函數結束括弧 } code.Append("} }"); //添加類結束和命名空間結束括弧 //得到編譯器執行個體的返回結果 CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString()); try { ; } catch { } if (cr.Errors.HasErrors) //如果有錯誤 { StringBuilder error = new StringBuilder(); //建立錯誤資訊字串 error.Append("編譯有錯誤的運算式: "); //添加錯誤文本 foreach (CompilerError err in cr.Errors) //遍曆每一個出現的編譯錯誤 { error.AppendFormat("{0}\n", err.ErrorText); //添加進錯誤文本,每個錯誤後換行 } MessageBox.Show("編譯錯誤: " + error.ToString()); return; } Assembly a = cr.CompiledAssembly; //擷取編譯器執行個體的程式集 _Compiled = a.CreateInstance("EvalGuy._Evaluator"); //通過程式集尋找並聲明 EvalGuy._Evaluator 的執行個體 }
至於這個工具作用,那篇文章寫的很清楚了:基本沒用。。。至少我這2個星期在工作中沒用到它。
菜鳥工具,Demo