执行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 ///12 /// 本类用来将字符串转为可执行文本并执行 13 /// 从别处复制,勿随意更改! 14 /// 15 public class Evaluator 16 { 17 #region 构造函数 18 /// 19 /// 可执行串的构造函数 20 /// 21 /// 22 /// 可执行字符串数组 23 /// 24 public Evaluator(EvaluatorItem[] items) 25 { 26 ConstructEvaluator(items); //调用解析字符串构造函数进行解析 27 } 28 /// 29 /// 可执行串的构造函数 30 /// 31 /// 返回值类型 32 /// 执行表达式 33 /// 执行字符串名称 34 public Evaluator(Type returnType, string expression, string name) 35 { 36 //创建可执行字符串数组 37 EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) }; 38 ConstructEvaluator(items); //调用解析字符串构造函数进行解析 39 } 40 /// 41 /// 可执行串的构造函数 42 /// 43 /// 可执行字符串项 44 public Evaluator(EvaluatorItem item) 45 { 46 EvaluatorItem[] items = { item };//将可执行字符串项转为可执行字符串项数组 47 ConstructEvaluator(items); //调用解析字符串构造函数进行解析 48 } 49 /// 50 /// 解析字符串构造函数 51 /// 52 /// 待解析字符串数组 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 /// 110 /// 执行字符串并返回整型值 111 /// 112 /// 执行字符串名称 113 /// 执行结果 114 public int EvaluateInt(string name) 115 { 116 return (int)Evaluate(name); 117 } 118 /// 119 /// 执行字符串并返回字符串型值 120 /// 121 /// 执行字符串名称 122 /// 执行结果 123 public string EvaluateString(string name) 124 { 125 return (string)Evaluate(name); 126 } 127 /// 128 /// 执行字符串并返回布尔型值 129 /// 130 /// 执行字符串名称 131 /// 执行结果 132 public bool EvaluateBool(string name) 133 { 134 return (bool)Evaluate(name); 135 } 136 /// 137 /// 执行字符串并返 object 型值 138 /// 139 /// 执行字符串名称 140 /// 执行结果 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 /// 150 /// 执行表达式并返回整型值 151 /// 152 /// 要执行的表达式 153 /// 运算结果 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 /// 160 /// 执行表达式并返回字符串型值 161 /// 162 /// 要执行的表达式 163 /// 运算结果 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 /// 170 /// 执行表达式并返回布尔型值 171 /// 172 /// 要执行的表达式 173 /// 运算结果 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 /// 180 /// 执行表达式并返回 object 型值 181 /// 182 /// 要执行的表达式 183 /// 运算结果 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 /// 193 /// 静态方法的执行字符串名称 194 /// 195 private const string staticMethodName = "__foo"; 196 /// 197 /// 用于动态引用生成的类,执行其内部包含的可执行字符串 198 /// 199 object _Compiled = null; 200 #endregion 201 } 202 /// 203 /// 可执行字符串项(即一条可执行字符串) 204 /// 205 public class EvaluatorItem 206 { 207 /// 208 /// 返回值类型 209 /// 210 public Type ReturnType; 211 /// 212 /// 执行表达式 213 /// 214 public string Expression; 215 /// 216 /// 执行字符串名称 217 /// 218 public string Name; 219 /// 220 /// 可执行字符串项构造函数 221 /// 222 /// 返回值类型 223 /// 执行表达式 224 /// 执行字符串名称 225 public EvaluatorItem(Type returnType, string expression, string name) 226 { 227 ReturnType = returnType; 228 Expression = expression; 229 Name = name; 230 } 231 } 232 }