像javascript中有eval()来执行动态代码,c#中是没有的,于是自己动手丰衣足食,
先来代码
代码语言:javascript复制 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 using System.Collections.Generic;
9
10 namespace 检漏仪上位机
11 {
12 /// <summary>
13 /// 本类用来将字符串转为可执行文本并执行
14 /// 从别处复制,勿随意更改!
15 /// </summary>
16 public class Evaluator
17 {
18 #region 构造函数
19 /// <summary>
20 /// 可执行串的构造函数
21 /// </summary>
22 /// <param name="items">
23 /// 可执行字符串数组
24 /// </param>
25 public Evaluator(EvaluatorItem[] items, Dictionary<string, string> listAssemblies = null)
26 {
27 ConstructEvaluator(items, listAssemblies); //调用解析字符串构造函数进行解析
28 }
29 /// <summary>
30 /// 可执行串的构造函数
31 /// </summary>
32 /// <param name="returnType">返回值类型</param>
33 /// <param name="expression">执行表达式</param>
34 /// <param name="name">执行字符串名称</param>
35 public Evaluator(Type returnType, string expression, string name, Dictionary<string, string> listAssemblies = null)
36 {
37 //创建可执行字符串数组
38 EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) };
39 ConstructEvaluator(items, listAssemblies); //调用解析字符串构造函数进行解析
40 }
41
42 public Evaluator(string allCode, string _namespace, string _class, List<string> listAssemblies = null)
43 {
44 ConstructEvaluatorByAllCode(allCode, _namespace, _class, listAssemblies); //调用解析字符串构造函数进行解析
45 }
46 /// <summary>
47 /// 可执行串的构造函数
48 /// </summary>
49 /// <param name="item">可执行字符串项</param>
50 public Evaluator(EvaluatorItem item, Dictionary<string, string> listAssemblies = null)
51 {
52 EvaluatorItem[] items = { item };//将可执行字符串项转为可执行字符串项数组
53 ConstructEvaluator(items, listAssemblies); //调用解析字符串构造函数进行解析
54 }
55 /// <summary>
56 /// 解析字符串构造函数
57 /// </summary>
58 /// <param name="items">待解析字符串数组</param>
59 private void ConstructEvaluator(EvaluatorItem[] items, Dictionary<string, string> listAssemblies = null)
60 {
61
62 //创建C#编译器实例
63 ICodeCompiler comp = (new CSharpCodeProvider().CreateCompiler());
64 //编译器的传入参数
65 CompilerParameters cp = new CompilerParameters();
66
67 cp.ReferencedAssemblies.Add("system.dll"); //添加程序集 system.dll 的引用
68 cp.ReferencedAssemblies.Add("system.data.dll"); //添加程序集 system.data.dll 的引用
69 cp.ReferencedAssemblies.Add("system.xml.dll"); //添加程序集 system.xml.dll 的引用
70 cp.ReferencedAssemblies.Add("System.Windows.Forms.dll"); //添加程序集 system.xml.dll 的引用
71 cp.GenerateExecutable = false; //不生成可执行文件
72 cp.GenerateInMemory = true; //在内存中运行
73
74 StringBuilder code = new StringBuilder(); //创建代码串
75 if (listAssemblies != null)
76 {
77 foreach (var item in listAssemblies)
78 {
79 cp.ReferencedAssemblies.Add(item.Key); //添加程序集 引用
80 code.Append("using " item.Value "; n");
81
82 }
83 }
84 /*
85 * 添加常见且必须的引用字符串
86 */
87 code.Append("using System; n");
88 code.Append("using System.Data; n");
89 code.Append("using System.Data.SqlClient; n");
90 code.Append("using System.Data.OleDb; n");
91 code.Append("using System.Xml; n");
92 code.Append("using System.Windows.Forms; n");
93
94 code.Append("namespace EvalGuy { n"); //生成代码的命名空间为EvalGuy,和本代码一样
95
96 code.Append(" public class _Evaluator { n"); //产生 _Evaluator 类,所有可执行代码均在此类中运行
97 foreach (EvaluatorItem item in items) //遍历每一个可执行字符串项
98 {
99 code.AppendFormat(" public {0} {1}() ", //添加定义公共函数代码
100 item.ReturnType == null ? "void" : item.ReturnType.Name, //函数返回值为可执行字符串项中定义的返回值类型
101 item.Name); //函数名称为可执行字符串项中定义的执行字符串名称
102 code.Append("{ "); //添加函数开始括号
103 if (item.ReturnType != null)
104 code.AppendFormat("return ({0});", item.Expression);//添加函数体,返回可执行字符串项中定义的表达式的值
105 else
106 {
107 code.Append(item.Expression);//添加函数体,返回可执行字符串项中定义的表达式的值
108 }
109 code.Append("}n"); //添加函数结束括号
110 }
111 code.Append("} }"); //添加类结束和命名空间结束括号
112
113 //得到编译器实例的返回结果
114 CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString());
115
116 if (cr.Errors.HasErrors) //如果有错误
117 {
118 StringBuilder error = new StringBuilder(); //创建错误信息字符串
119 error.Append("编译有错误的表达式: "); //添加错误文本
120 foreach (CompilerError err in cr.Errors) //遍历每一个出现的编译错误
121 {
122 error.AppendFormat("{0}n", err.ErrorText); //添加进错误文本,每个错误后换行
123 }
124 throw new Exception("编译错误: " error.ToString());//抛出异常
125 }
126 Assembly a = cr.CompiledAssembly; //获取编译器实例的程序集
127 _Compiled = a.CreateInstance("EvalGuy._Evaluator"); //通过程序集查找并声明 EvalGuy._Evaluator 的实例
128 }
129
130 private void ConstructEvaluatorByAllCode(string allcode, string _namespace, string _class, List<string> listAssemblies)
131 {
132 if (listAssemblies == null)
133 {
134 listAssemblies = new List<string>();
135 }
136 //创建C#编译器实例
137 ICodeCompiler comp = (new CSharpCodeProvider().CreateCompiler());
138 //编译器的传入参数
139 CompilerParameters cp = new CompilerParameters();
140 if (!listAssemblies.Contains("system.dll"))
141 {
142 listAssemblies.Add("system.dll");
143 listAssemblies.Add("system.data.dll");
144 listAssemblies.Add("system.xml.dll");
145 }
146 foreach (var item in listAssemblies)
147 {
148 cp.ReferencedAssemblies.Add(item);
149 }
150
151 cp.GenerateExecutable = false; //不生成可执行文件
152 cp.GenerateInMemory = true; //在内存中运行
153
154
155 //得到编译器实例的返回结果
156 CompilerResults cr = comp.CompileAssemblyFromSource(cp, allcode);
157
158 if (cr.Errors.HasErrors) //如果有错误
159 {
160 StringBuilder error = new StringBuilder(); //创建错误信息字符串
161 error.Append("编译有错误的表达式: "); //添加错误文本
162 foreach (CompilerError err in cr.Errors) //遍历每一个出现的编译错误
163 {
164 error.AppendFormat("{0}n", err.ErrorText); //添加进错误文本,每个错误后换行
165 }
166 throw new Exception("编译错误: " error.ToString());//抛出异常
167 }
168 Assembly a = cr.CompiledAssembly; //获取编译器实例的程序集
169 _Compiled = a.CreateInstance($"{_namespace}.{_class}"); //通过程序集查找并声明 EvalGuy._Evaluator 的实例
170 }
171 #endregion
172
173 #region 公有成员
174 /// <summary>
175 /// 执行字符串并返回整型值
176 /// </summary>
177 /// <param name="name">执行字符串名称</param>
178 /// <returns>执行结果</returns>
179 public int EvaluateInt(string name)
180 {
181 return (int)Evaluate(name);
182 }
183 /// <summary>
184 /// 执行字符串并返回字符串型值
185 /// </summary>
186 /// <param name="name">执行字符串名称</param>
187 /// <returns>执行结果</returns>
188 public string EvaluateString(string name)
189 {
190 return (string)Evaluate(name);
191 }
192 /// <summary>
193 /// 执行字符串并返回布尔型值
194 /// </summary>
195 /// <param name="name">执行字符串名称</param>
196 /// <returns>执行结果</returns>
197 public bool EvaluateBool(string name)
198 {
199 return (bool)Evaluate(name);
200 }
201 /// <summary>
202 /// 执行字符串并返 object 型值
203 /// </summary>
204 /// <param name="name">执行字符串名称</param>
205 /// <returns>执行结果</returns>
206 public object Evaluate(string name)
207 {
208 MethodInfo mi = _Compiled.GetType().GetMethod(name);//获取 _Compiled 所属类型中名称为 name 的方法的引用
209 return mi.Invoke(_Compiled, null); //执行 mi 所引用的方法
210 }
211 #endregion
212
213 #region 静态成员
214 /// <summary>
215 /// 执行表达式并返回整型值
216 /// </summary>
217 /// <param name="code">要执行的表达式</param>
218 /// <param name="listAssemblies">需要引用到类库,key:dll名称,value:命名空间名称</param>
219 /// <returns>运算结果</returns>
220 static public int EvaluateToInteger(string code, Dictionary<string, string> listAssemblies = null)
221 {
222 Evaluator eval = new Evaluator(typeof(int), code, staticMethodName, listAssemblies);//生成 Evaluator 类的对像
223 return (int)eval.Evaluate(staticMethodName); //执行并返回整型数据
224 }
225 /// <summary>
226 /// 执行表达式并返回字符串型值
227 /// </summary>
228 /// <param name="code">要执行的表达式</param>
229 /// <param name="listAssemblies">需要引用到类库,key:dll名称,value:命名空间名称</param>
230 /// <returns>运算结果</returns>
231 static public string EvaluateToString(string code, Dictionary<string, string> listAssemblies = null)
232 {
233 Evaluator eval = new Evaluator(typeof(string), code, staticMethodName, listAssemblies);//生成 Evaluator 类的对像
234 return (string)eval.Evaluate(staticMethodName); //执行并返回字符串型数据
235 }
236 /// <summary>
237 /// 执行表达式并返回布尔型值
238 /// </summary>
239 /// <param name="code">要执行的表达式</param>
240 /// <param name="listAssemblies">需要引用到类库,key:dll名称,value:命名空间名称</param>
241 /// <returns>运算结果</returns>
242 static public bool EvaluateToBool(string code, Dictionary<string, string> listAssemblies = null)
243 {
244 Evaluator eval = new Evaluator(typeof(bool), code, staticMethodName, listAssemblies);//生成 Evaluator 类的对像
245 return (bool)eval.Evaluate(staticMethodName); //执行并返回布尔型数据
246 }
247 /// <summary>
248 /// 执行表达式并返回 object 型值
249 /// </summary>
250 /// <param name="code">要执行的表达式</param>
251 /// <param name="listAssemblies">需要引用到类库,key:dll名称,value:命名空间名称</param>
252 /// <returns>运算结果</returns>
253 static public object EvaluateToObject(string code, Dictionary<string, string> listAssemblies = null)
254 {
255 Evaluator eval = new Evaluator(typeof(object), code, staticMethodName, listAssemblies);//生成 Evaluator 类的对像
256 return eval.Evaluate(staticMethodName); //执行并返回 object 型数据
257 }
258 /// <summary>
259 /// 执行一个无返回式的代码
260 /// </summary>
261 /// <param name="code"></param>
262 /// <param name="listAssemblies">需要引用到类库,key:dll名称,value:命名空间名称</param>
263 static public void EvaluateToVoid(string code, Dictionary<string, string> listAssemblies = null)
264 {
265 Evaluator eval = new Evaluator(null, code, staticMethodName, listAssemblies);//生成 Evaluator 类的对像
266 eval.Evaluate(staticMethodName); //执行并返回 object 型数据
267 }
268 /// <summary>
269 /// 执行一个全代码
270 /// </summary>
271 /// <param name="code">全代码,包含命名空间引用,命名空间声明,类声明,函数声明等</param>
272 /// <param name="_namespace"></param>
273 /// <param name="_class"></param>
274 /// <param name="methodName">函数</param>
275 /// <param name="listAssemblies">需要引用到类库</param>
276 public static void EvaluateByAllCode(string code, string _namespace, string _class, string methodName, List<string> listAssemblies = null)
277 {
278 Evaluator eval = new Evaluator(code, _namespace, _class, listAssemblies);//生成 Evaluator 类的对像
279 eval.Evaluate(methodName);
280 }
281 #endregion
282
283 #region 私有成员
284 /// <summary>
285 /// 静态方法的执行字符串名称
286 /// </summary>
287 private const string staticMethodName = "__foo";
288 /// <summary>
289 /// 用于动态引用生成的类,执行其内部包含的可执行字符串
290 /// </summary>
291 object _Compiled = null;
292 #endregion
293 }
294 /// <summary>
295 /// 可执行字符串项(即一条可执行字符串)
296 /// </summary>
297 public class EvaluatorItem
298 {
299 /// <summary>
300 /// 返回值类型
301 /// </summary>
302 public Type ReturnType;
303 /// <summary>
304 /// 执行表达式
305 /// </summary>
306 public string Expression;
307 /// <summary>
308 /// 执行字符串名称
309 /// </summary>
310 public string Name;
311 /// <summary>
312 /// 可执行字符串项构造函数
313 /// </summary>
314 /// <param name="returnType">返回值类型</param>
315 /// <param name="expression">执行表达式</param>
316 /// <param name="name">执行字符串名称</param>
317 public EvaluatorItem(Type returnType, string expression, string name)
318 {
319 ReturnType = returnType;
320 Expression = expression;
321 Name = name;
322 }
323 }
324 }
调用一个无返回值的代码,显示一个提示框
代码语言:javascript复制Evaluator.EvaluateToVoid("MessageBox.Show("Test");",new Dictionary<string, string>() { { "System.Windows.Forms.dll", "System.Windows.Forms" } });
调用一个计算返回整型
代码语言:javascript复制 Evaluator.EvaluateToInteger("1 2*3");
调用一个全代码
代码语言:javascript复制 string str = @"using System;
namespace a
{
public class b
{
public void c()
{
Console.WriteLine(1);
}
}
}";
Evaluator.EvaluateByAllCode(str, "a", "b", "c");
功能就这么多