像javascript中有eval()来执行动态代码,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 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 }

调用一个无返回值的代码,显示一个提示框

Evaluator.EvaluateToVoid("MessageBox.Show(\"Test\");",new Dictionary<string, string>() { { "System.Windows.Forms.dll", "System.Windows.Forms" } });

调用一个计算返回整型

            Evaluator.EvaluateToInteger("1+2*3");

调用一个全代码

            string str = @"using System;
namespace a
{
public class b
{
public void c()
{
Console.WriteLine(1);
}
}
}"; Evaluator.EvaluateByAllCode(str, "a", "b", "c");

功能就这么多

c#动态执行字符串脚本(优化版)的更多相关文章

  1. 动态执行python脚本

    前言 存在许多独立的python脚本,这些脚本可能会增加,也可能会减少,现在需要按照某种顺序调度这些程序.在python的standard library中,有一个模块imp可以实现动态的调用ptho ...

  2. C#动态执行字符串(动态创建代码)

    在编写C#程序的时候,有时我们需要动态生成一些代码并执行.然而C#不像JavaScript有一个Eval函数,可以动态的执行代码.所有这些功能都要我们自己去完成.如下是实例. 动态创建代码: usin ...

  3. CENTOS 7 内网网段在用IP地址检测Shell脚本优化版

    脚本内容 #!/bin/bash ############################################################################# # 用途: ...

  4. MYSQL动态查询拼接的表名的SQL脚本实现(MYSQL动态执行SQL脚本)

    可以使用MYSQL的预处理逻辑:https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-prepared-statements.html   例如: pr ...

  5. 利用python执行shell脚本 并动态传参 及subprocess基本使用

    最近工作需求中 有遇到这个情况  在web端获取配置文件内容 及 往shell 脚本中动态传入参数 执行shell脚本这个有多种方法   最后还是选择了subprocess这个python标准库 su ...

  6. Sql动态查询拼接字符串的优化

    Sql动态查询拼接字符串的优化 最原始的 直接写:string sql="select * from TestTables where 1=1";... 这样的代码效率很低的,这样 ...

  7. c# 动态执行脚本,相关的几个脚本引擎.

    Jint   嵌入式的javascript脚本支持引擎,一直都在更新,对各种方法支持也比较好,可以 C# 交互. https://github.com/sebastienros/jint Jurass ...

  8. 在本地主机上powershell中连接远程主机执行vbs脚本,得到执行结果(2008版及以上)

    在桌面版的主机上远程管理服务器版主机,在本地powershell中连接远程主机执行vbs脚本,得到执行结果. 执行步骤: 1.将本地主机上的Hyper.vbs复制到远程连接主机上.例如,本地vbs脚本 ...

  9. MonkeyRunner执行Python脚本实例——发送短信增强版

    很久之前就写好的了,准备写个自动执行Monkey的脚本时才想到去找它,还是写在博客里找起来方便. 这次更新了批处理自动连接设备后执行Py脚本,结构如下图: 其中shotscreen为存放截图文件夹,s ...

  10. mysql 字符串分割 和 动态执行拼接sql

    本人以前主要用的是MSSQL,最近项目在使用MYSQL,自己是一个 典型的小白.今天就记录一下 一个mysql存储过程,里面需要分割字符串和 动态执行sql语句. 关于字符串 分割我开始使用 LOCA ...

随机推荐

  1. AD9834配置

    SPI设置 注意,虽然手册上CPOL(CLK空闲时电平)为低,但实测是是高电平 连接 SYNC 为片选引脚,使用时拉低 FSE/PSE为频率与相位寄存器选择,均拉低即可 void SPI_Write_ ...

  2. 威纶通作为modbusTcp主站应用

    1.在威纶通中添加modbus Tcp,作为主机,在Tcp服务器客户端模型中作为客户端: 2.威纶通地址与modbus标准功能码的对应关系: 地址1x_single_Bit,对应02功能码(读输入线圈 ...

  3. find_in_set使用:匹配按逗号分隔后的内容

    SELECT  * FROM `tb_test` WHERE c_id ='123' AND create_time LIKE '2021-06-03%'  AND find_in_set('A362 ...

  4. ES6 之 Promise

    promise 与ajax 实现两个ajax返回参数的拼接 // 函数 fetch() { return new Promise((resolve, reject) => { Utils.sen ...

  5. openSuse Tumbleweed 安装钉钉

    办公软件钉钉提供了 Linux 版本,但是只有deb安装包. https://page.dingtalk.com/wow/z/dingtalk/default/dddownload-index ope ...

  6. Linux使用NAT/VMnet8(NAT)模式配置网卡ping通外网/主机/百度

    vmnat 配置好后无法ping通打开共享 vmnet8 nat网卡配置 主机网卡配置 去掉网关

  7. angular 父组件调用子组件的方法

  8. 关于pandas的一些用法

    pandas用法之前我总是把他想的无比复杂.其实也是比较简单的,这个东西在做数据统计的时候还是挺好用的. 然后这里列举几个比较好用的几段代码.偏向数据透视类型pivot的,导出方式是直接在IDE 生成 ...

  9. 关于git错误:Git未能顺利结束(退出码 128)的解决办法

    如图: 问题原因: 主要是:用户名.邮箱.用户密钥跟github官网上配置的不一致 https://blog.csdn.net/weixin_52517585/article/details/1269 ...

  10. 模拟法NOIP题单

    模拟算法的试题训练, 重点针对试题分析环节的练习锻炼!! 考察阅读能力.分析能力.建模能力! 模拟法题目是最基础的题目,她不难,她复杂,她的实现往往需要足够的细心耐心! 练习这类题目能够使你掌握其他算 ...