執行C#動態代碼
1 using System; 2 using System.Data; 3 using System.Configuration; 4 using System.Text; 5 using System.CodeDom.Compiler; 6 using Microsoft.CSharp; 7 using System.Reflection; 8 9 namespace EvalGuy 10 { 11 /// <summary> 12 /// 本類用來將字符串轉為可執行文本並執行 13 /// 從別處復制,勿隨意更改! 14 /// </summary> 15 public class Evaluator 16 { 17 #region 構造函數 18 /// <summary> 19 /// 可執行串的構造函數 20 /// </summary> 21 /// <param name="items"> 22 /// 可執行字符串數組 23 /// </param> 24 public Evaluator(EvaluatorItem[] items) 25 { 26 ConstructEvaluator(items); //調用解析字符串構造函數進行解析 27 } 28 /// <summary> 29 /// 可執行串的構造函數 30 /// </summary> 31 /// <param name="returnType">返回值類型</param> 32 /// <param name="expression">執行表達式</param> 33 /// <param name="name">執行字符串名稱</param> 34 public Evaluator(Type returnType, string expression, string name) 35 { 36 //創建可執行字符串數組 37 EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) }; 38 ConstructEvaluator(items); //調用解析字符串構造函數進行解析 39 } 40 /// <summary> 41 /// 可執行串的構造函數 42 /// </summary> 43 /// <param name="item">可執行字符串項</param> 44 public Evaluator(EvaluatorItem item) 45 { 46 EvaluatorItem[] items = { item };//將可執行字符串項轉為可執行字符串項數組 47 ConstructEvaluator(items); //調用解析字符串構造函數進行解析 48 } 49 /// <summary> 50 /// 解析字符串構造函數 51 /// </summary> 52 /// <param name="items">待解析字符串數組</param> 53 private void ConstructEvaluator(EvaluatorItem[] items) 54 { 55 //創建C#編譯器實例 56 ICodeCompiler comp = (new CSharpCodeProvider().CreateCompiler()); 57 //編譯器的傳入參數 58 CompilerParameters cp = new CompilerParameters(); 59 60 cp.ReferencedAssemblies.Add("system.dll"); //添加程序集 system.dll 的引用 61 cp.ReferencedAssemblies.Add("system.data.dll"); //添加程序集 system.data.dll 的引用 62 cp.ReferencedAssemblies.Add("system.xml.dll"); //添加程序集 system.xml.dll 的引用 63 cp.GenerateExecutable = false; //不生成可執行文件 64 cp.GenerateInMemory = true; //在內存中運行 65 66 StringBuilder code = new StringBuilder(); //創建代碼串 67 /* 68 * 添加常見且必須的引用字符串 69 */ 70 code.Append("using System; \n"); 71 code.Append("using System.Data; \n"); 72 code.Append("using System.Data.SqlClient; \n"); 73 code.Append("using System.Data.OleDb; \n"); 74 code.Append("using System.Xml; \n"); 75 76 code.Append("namespace EvalGuy { \n"); //生成代碼的命名空間為EvalGuy,和本代碼一樣 77 78 code.Append(" public class _Evaluator { \n"); //產生 _Evaluator 類,所有可執行代碼均在此類中運行 79 foreach (EvaluatorItem item in items) //遍歷每一個可執行字符串項 80 { 81 code.AppendFormat(" public {0} {1}() ", //添加定義公共函數代碼 82 item.ReturnType.Name, //函數返回值為可執行字符串項中定義的返回值類型 83 item.Name); //函數名稱為可執行字符串項中定義的執行字符串名稱 84 code.Append("{ "); //添加函數開始括號 85 code.AppendFormat("return ({0});", item.Expression);//添加函數體,返回可執行字符串項中定義的表達式的值 86 code.Append("}\n"); //添加函數結束括號 87 } 88 code.Append("} }"); //添加類結束和命名空間結束括號 89 90 //得到編譯器實例的返回結果 91 CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString()); 92 93 if (cr.Errors.HasErrors) //如果有錯誤 94 { 95 StringBuilder error = new StringBuilder(); //創建錯誤信息字符串 96 error.Append("編譯有錯誤的表達式: "); //添加錯誤文本 97 foreach (CompilerError err in cr.Errors) //遍歷每一個出現的編譯錯誤 98 { 99 error.AppendFormat("{0}\n", err.ErrorText); //添加進錯誤文本,每個錯誤后換行 100 } 101 throw new Exception("編譯錯誤: " + error.ToString());//拋出異常 102 } 103 Assembly a = cr.CompiledAssembly; //獲取編譯器實例的程序集 104 _Compiled = a.CreateInstance("EvalGuy._Evaluator"); //通過程序集查找並聲明 EvalGuy._Evaluator 的實例 105 } 106 #endregion 107 108 #region 公有成員 109 /// <summary> 110 /// 執行字符串並返回整型值 111 /// </summary> 112 /// <param name="name">執行字符串名稱</param> 113 /// <returns>執行結果</returns> 114 public int EvaluateInt(string name) 115 { 116 return (int)Evaluate(name); 117 } 118 /// <summary> 119 /// 執行字符串並返回字符串型值 120 /// </summary> 121 /// <param name="name">執行字符串名稱</param> 122 /// <returns>執行結果</returns> 123 public string EvaluateString(string name) 124 { 125 return (string)Evaluate(name); 126 } 127 /// <summary> 128 /// 執行字符串並返回布爾型值 129 /// </summary> 130 /// <param name="name">執行字符串名稱</param> 131 /// <returns>執行結果</returns> 132 public bool EvaluateBool(string name) 133 { 134 return (bool)Evaluate(name); 135 } 136 /// <summary> 137 /// 執行字符串並返 object 型值 138 /// </summary> 139 /// <param name="name">執行字符串名稱</param> 140 /// <returns>執行結果</returns> 141 public object Evaluate(string name) 142 { 143 MethodInfo mi = _Compiled.GetType().GetMethod(name);//獲取 _Compiled 所屬類型中名稱為 name 的方法的引用 144 return mi.Invoke(_Compiled, null); //執行 mi 所引用的方法 145 } 146 #endregion 147 148 #region 靜態成員 149 /// <summary> 150 /// 執行表達式並返回整型值 151 /// </summary> 152 /// <param name="code">要執行的表達式</param> 153 /// <returns>運算結果</returns> 154 static public int EvaluateToInteger(string code) 155 { 156 Evaluator eval = new Evaluator(typeof(int), code, staticMethodName);//生成 Evaluator 類的對像 157 return (int)eval.Evaluate(staticMethodName); //執行並返回整型數據 158 } 159 /// <summary> 160 /// 執行表達式並返回字符串型值 161 /// </summary> 162 /// <param name="code">要執行的表達式</param> 163 /// <returns>運算結果</returns> 164 static public string EvaluateToString(string code) 165 { 166 Evaluator eval = new Evaluator(typeof(string), code, staticMethodName);//生成 Evaluator 類的對像 167 return (string)eval.Evaluate(staticMethodName); //執行並返回字符串型數據 168 } 169 /// <summary> 170 /// 執行表達式並返回布爾型值 171 /// </summary> 172 /// <param name="code">要執行的表達式</param> 173 /// <returns>運算結果</returns> 174 static public bool EvaluateToBool(string code) 175 { 176 Evaluator eval = new Evaluator(typeof(bool), code, staticMethodName);//生成 Evaluator 類的對像 177 return (bool)eval.Evaluate(staticMethodName); //執行並返回布爾型數據 178 } 179 /// <summary> 180 /// 執行表達式並返回 object 型值 181 /// </summary> 182 /// <param name="code">要執行的表達式</param> 183 /// <returns>運算結果</returns> 184 static public object EvaluateToObject(string code) 185 { 186 Evaluator eval = new Evaluator(typeof(object), code, staticMethodName);//生成 Evaluator 類的對像 187 return eval.Evaluate(staticMethodName); //執行並返回 object 型數據 188 } 189 #endregion 190 191 #region 私有成員 192 /// <summary> 193 /// 靜態方法的執行字符串名稱 194 /// </summary> 195 private const string staticMethodName = "__foo"; 196 /// <summary> 197 /// 用於動態引用生成的類,執行其內部包含的可執行字符串 198 /// </summary> 199 object _Compiled = null; 200 #endregion 201 } 202 /// <summary> 203 /// 可執行字符串項(即一條可執行字符串) 204 /// </summary> 205 public class EvaluatorItem 206 { 207 /// <summary> 208 /// 返回值類型 209 /// </summary> 210 public Type ReturnType; 211 /// <summary> 212 /// 執行表達式 213 /// </summary> 214 public string Expression; 215 /// <summary> 216 /// 執行字符串名稱 217 /// </summary> 218 public string Name; 219 /// <summary> 220 /// 可執行字符串項構造函數 221 /// </summary> 222 /// <param name="returnType">返回值類型</param> 223 /// <param name="expression">執行表達式</param> 224 /// <param name="name">執行字符串名稱</param> 225 public EvaluatorItem(Type returnType, string expression, string name) 226 { 227 ReturnType = returnType; 228 Expression = expression; 229 Name = name; 230 } 231 } 232 }
