【转】C# 将字符串或表达式直接转为可执行代码的办法
C# 将字符串或表达式直接转为可执行代码的办法
反射类
using System;
using System.Data;
using System.Configuration;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;
namespace SSEC.Math
{
/// <summary>
/// 本类用来将字符串转为可执行文本并执行
/// </summary>
public class MyEvaluator
{
#region 构造函数
/// <summary>
/// 可执行串的构造函数
/// </summary>
/// <param name="items">
/// 可执行字符串数组
/// </param>
public MyEvaluator(EvaluatorItem[] items)
{
ConstructEvaluator(items); //调用解析字符串构造函数进行解析
}
/// <summary>
/// 可执行串的构造函数
/// </summary>
/// <param name="returnType">返回值类型</param>
/// <param name="expression">执行表达式</param>
/// <param name="name">执行字符串名称</param>
public MyEvaluator(Type returnType, string expression, string name)
{
//创建可执行字符串数组
EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) };
ConstructEvaluator(items); //调用解析字符串构造函数进行解析
}
/// <summary>
/// 可执行串的构造函数
/// </summary>
/// <param name="item">可执行字符串项</param>
public MyEvaluator(EvaluatorItem item)
{
EvaluatorItem[] items = { item };//将可执行字符串项转为可执行字符串项数组
ConstructEvaluator(items); //调用解析字符串构造函数进行解析
}
/// <summary>
/// 解析字符串构造函数
/// </summary>
/// <param name="items">待解析字符串数组</param>
private void ConstructEvaluator(EvaluatorItem[] items)
{
//创建C#编译器实例
CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
//过时了
//ICodeCompiler comp = provider.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 SSEC.Math { /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("{ "); //添加函数开始括号
code.AppendFormat("return ({0});", item.Expression);//添加函数体,返回可执行字符串项中定义的表达式的值
code.Append("}/n"); //添加函数结束括号
}
code.Append("} }"); //添加类结束和命名空间结束括号
//得到编译器实例的返回结果
CompilerResults cr = provider.CompileAssemblyFromSource(cp, code.ToString());//comp
if (cr.Errors.HasErrors) //如果有错误
{
StringBuilder error = new StringBuilder(); //创建错误信息字符串
error.Append("编译有错误的表达式: "); //添加错误文本
foreach (CompilerError err in cr.Errors) //遍历每一个出现的编译错误
{
error.AppendFormat("{0}/n", err.ErrorText); //添加进错误文本,每个错误后换行
}
throw new Exception("编译错误: " + error.ToString());//抛出异常
}
Assembly a = cr.CompiledAssembly; //获取编译器实例的程序集
_Compiled = a.CreateInstance("SSEC.Math._Evaluator"); //通过程序集查找并声明 SSEC.Math._Evaluator 的实例
}
#endregion
#region 公有成员
/// <summary>
/// 执行字符串并返回整型值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
public int EvaluateInt(string name)
{
return (int)Evaluate(name);
}
/// <summary>
/// 执行字符串并返回双精度值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
public double EvaluateDouble(string name)
{
return (double)Evaluate(name);
}
/// <summary>
/// 执行字符串并返回长整型数值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
public long EvaluateLong(string name)
{
return (long)Evaluate(name);
}
/// <summary>
/// 执行字符串并返回十进制数值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
public decimal EvaluateDecimal(string name)
{
return (decimal)Evaluate(name);
}
/// <summary>
/// 执行字符串并返回字符串型值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
public string EvaluateString(string name)
{
return (string)Evaluate(name);
}
/// <summary>
/// 执行字符串并返回布尔型值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
public bool EvaluateBool(string name)
{
return (bool)Evaluate(name);
}
/// <summary>
/// 执行字符串并返 object 型值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
public object Evaluate(string name)
{
MethodInfo mi = _Compiled.GetType().GetMethod(name);//获取 _Compiled 所属类型中名称为 name 的方法的引用
return mi.Invoke(_Compiled, null); //执行 mi 所引用的方法
}
#endregion
#region 静态成员
/// <summary>
/// 执行表达式并返回整型值
/// </summary>
/// <param name="code">要执行的表达式</param>
/// <returns>运算结果</returns>
static public int EvaluateToInteger(string code)
{
MyEvaluator eval = new MyEvaluator(typeof(int), code, staticMethodName);//生成 Evaluator 类的对像
return (int)eval.Evaluate(staticMethodName); //执行并返回整型数据
}
/// <summary>
/// 执行表达式并返回双精度值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
static public double EvaluateToDouble(string code)
{
MyEvaluator eval = new MyEvaluator(typeof(double), code, staticMethodName);//生成 Evaluator 类的对像
return (double)eval.Evaluate(staticMethodName);
}
/// <summary>
/// 执行表达式并返回长整型数值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
static public long EvaluateToLong(string code)
{
MyEvaluator eval = new MyEvaluator(typeof(long), code, staticMethodName);//生成 Evaluator 类的对像
return (long)eval.Evaluate(staticMethodName);
}
/// <summary>
/// 执行表达式并返回十进制数值
/// </summary>
/// <param name="name">执行字符串名称</param>
/// <returns>执行结果</returns>
static public decimal EvaluateToDecimal(string code)
{
MyEvaluator eval = new MyEvaluator(typeof(decimal), code, staticMethodName);//生成 Evaluator 类的对像
return (decimal)eval.Evaluate(staticMethodName);
}
/// <summary>
/// 执行表达式并返回字符串型值
/// </summary>
/// <param name="code">要执行的表达式</param>
/// <returns>运算结果</returns>
static public string EvaluateToString(string code)
{
MyEvaluator eval = new MyEvaluator(typeof(string), code, staticMethodName);//生成 Evaluator 类的对像
return (string)eval.Evaluate(staticMethodName); //执行并返回字符串型数据
}
/// <summary>
/// 执行表达式并返回布尔型值
/// </summary>
/// <param name="code">要执行的表达式</param>
/// <returns>运算结果</returns>
static public bool EvaluateToBool(string code)
{
MyEvaluator eval = new MyEvaluator(typeof(bool), code, staticMethodName);//生成 Evaluator 类的对像
return (bool)eval.Evaluate(staticMethodName); //执行并返回布尔型数据
}
/// <summary>
/// 执行表达式并返回 object 型值
/// </summary>
/// <param name="code">要执行的表达式</param>
/// <returns>运算结果</returns>
static public object EvaluateToObject(string code)
{
MyEvaluator eval = new MyEvaluator(typeof(object), code, staticMethodName);//生成 Evaluator 类的对像
return eval.Evaluate(staticMethodName); //执行并返回 object 型数据
}
#endregion
#region 私有成员
/// <summary>
/// 静态方法的执行字符串名称
/// </summary>
private const string staticMethodName = "__foo";
/// <summary>
/// 用于动态引用生成的类,执行其内部包含的可执行字符串
/// </summary>
object _Compiled = null;
#endregion
}
/// <summary>
/// 可执行字符串项(即一条可执行字符串)
/// </summary>
public class EvaluatorItem
{
/// <summary>
/// 返回值类型
/// </summary>
public Type ReturnType;
/// <summary>
/// 执行表达式
/// </summary>
public string Expression;
/// <summary>
/// 执行字符串名称
/// </summary>
public string Name;
/// <summary>
/// 可执行字符串项构造函数
/// </summary>
/// <param name="returnType">返回值类型</param>
/// <param name="expression">执行表达式</param>
/// <param name="name">执行字符串名称</param>
public EvaluatorItem(Type returnType, string expression, string name)
{
ReturnType = returnType;
Expression = expression;
Name = name;
}
}
}
测试类:
class Test
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Console.WriteLine("Test0: {0}", MyEvaluator.EvaluateToInteger("(30 + 4) * 2"));
Console.WriteLine("Test1: {0}", MyEvaluator.EvaluateToString("/"Hello /" + /"There/""));
Console.WriteLine("Test2: {0}", MyEvaluator.EvaluateToBool("30 == 40"));
Console.WriteLine("Test3: {0}", MyEvaluator.EvaluateToObject("new DataSet()"));
Console.WriteLine("Test4: {0}", MyEvaluator.EvaluateToDouble("(12.4+2.2)*0.4"));
Console.WriteLine("Test5: {0}", MyEvaluator.EvaluateToLong("(12+1000)*1000"));
Console.WriteLine("Test6: {0}", MyEvaluator.EvaluateToString("/"double max==/"+double.MaxValue"));//decimal.MaxValue+/",/"+
EvaluatorItem[] items = {
new EvaluatorItem(typeof(int), "(30 + 4) * 2", "GetNumber"),
new EvaluatorItem(typeof(string), "/"Hello /" + /"There/"", "GetString"),
new EvaluatorItem(typeof(bool), "30 == 40", "GetBool"),
new EvaluatorItem(typeof(object), "new DataSet()", "GetDataSet")
};
MyEvaluator eval = new MyEvaluator(items);
Console.WriteLine("TestStatic0: {0}", eval.EvaluateInt("GetNumber"));
Console.WriteLine("TestStatic1: {0}", eval.EvaluateString("GetString"));
Console.WriteLine("TestStatic2: {0}", eval.EvaluateBool("GetBool"));
Console.WriteLine("TestStatic3: {0}", eval.Evaluate("GetDataSet"));
Console.ReadLine();
}
}
【转】C# 将字符串或表达式直接转为可执行代码的办法的更多相关文章
- decode 函数将字符串从某种编码转为 unicode 字符
环境:Ubuntu, Python 2.7 基础知识 这个程序涉及到的知识点有几个,在这里列出来,不详细讲,有疑问的直接百度会有一堆的. 1.urllib2 模块的 request 对像来设置 HTT ...
- C# 字符串计算表达式
C# 字符串计算表达式 string str="4+4+2.1"; 要的效果: double sum=4+4+2.1: 方案一: 动态计算表达式: 1 public class ...
- 算法笔试题整理——升级蓄水池 && 字符串数字表达式计算值 && 求旅游完所有景点需要的最少天数 && 宝箱怪
1. 小米笔试题——升级蓄水池 题目描述: 在米兔生活的二维世界中,建造蓄水池非常简单. 一个蓄水池可以用n个坐标轴上的非负整数表示,代表区间为[0-n]范围内宽度为1的墙壁的高度. 如下图1,黑色部 ...
- 6. python 字符串格式化表达式
6. python 字符串格式化表达式 字符串格式化允许在一个单个的步骤中对一个字符串执行多个特定类型的替换 特别是给用户提示的时候,格式化非常方便 实现方法: 1.格式化表达式,类似于c语言的pri ...
- Lambda表达式, 可以让我们的代码更优雅.
在C#中, 适当地使用Lambda表达式, 可以让我们的代码更优雅. 通过lambda表达式, 我们可以很方便地创建一个delegate: 下面两个语句是等价的 Code highlighting p ...
- C#中分别对委托、匿名方法、Lambda表达式、Lambda表达式树以及反射执行同一方法的过程进行比较。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- c#字符串加载wpf控件模板代码 - 简书
原文:c#字符串加载wpf控件模板代码 - 简书 ResourceManager resManagerA = new ResourceManager("cn.qssq666.Properti ...
- Atitti. 语法树AST、后缀表达式、DAG、三地址代码
Atitti. 语法树AST.后缀表达式.DAG.三地址代码 抽象语法树的观点认为任何复杂的语句嵌套情况都可以借助于树的形式加以描述.确实,不得不承认应用抽象语法树可以使语句翻译变得相对容易,它很好地 ...
- 【字符串处理算法】字符串包括的算法设计及C代码实现
一.需求描写叙述 给定一个长字符串和一个短字符串.编敲代码推断短字符串中的全部字符是否都在长字符串中.假设是,则长字符串包括短字符串:反之,不包括. 为了尽量包括大多数情况,字符串中能够包括大写和小写 ...
随机推荐
- Linux系统用户和用户组介绍
1.请问如下登录环境故障的原理及解决办法? [root@server test]# useradd rr ##创建用户rr [root@server test]# id rr uid=510(rr) ...
- 文本处理三剑客之sed命令
第十八章.文本处理三剑客之sed命令 目录 sed介绍 sed命令常用选项 sed常用编辑命令 sed使用示例 sed高级语法 18.1.sed简介 sed全名stream editor,流编辑器,s ...
- rsync同步
本地同步: rsync -avz /boot /test C/S架构: 远程同步:rsync+ssh 远程浏览器目录文件:rsync 用户@192.168.0.250:/boot 下行:rsync ...
- Win10全屏看视频时任务栏不隐藏
解决办法: 1.对任务栏鼠标右键点击,选择"任务管理器" 2.在进程选项下找到Windows进程中的Windows资源管理器 3.对Windows资源管理器鼠标右键,选择重新启动
- 2-ser2003系统封装实验报告
Ser2003需要挂载系统镜像 至此,ser2003的母盘制作完成!!! 来自为知笔记(Wiz) 附件列表
- Ubuntu管理开机启动服务项 -- 图形界面的Boot-up Manager
有时学习时安装的服务太多,比如mysql.mongodb.redis.apache.nginx等等,它们都是默认开机启动的,如果不想让它们开机启动,用到时再自己手工启动怎么办呢? 使用sysv-rc- ...
- 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题
精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 例如:如下的矩阵 就包含了这样一个集合(第1.4.5行) 如何利用给定的矩阵求出相应的行的集合 ...
- Leetcode 99: Recovery binary search tree 总算明白了算法, 把代码写清楚, 让错误无处可藏.
想写点什么, 因为这道题花了我好几个小时, 在周日, 除了在球场上跑了二个小时, 就泡在这道题上面. read blogs: http://www.lifeincode.net/programming ...
- 基于pcDuino-V2的无线视频智能小车
这段时间抽空做了个智能视频小车.包含了pid电机控制.socket网络编程.多线程编程.epoll机制.gtk图形界面编程. 这是界面: 小车的底层是用的stm32f405系列的单片机+电机驱动做的一 ...
- Python mock
在测试过程中,为了更好地展开单元测试,mock一些数据跟对象在所难免,下面讲一下python的mock的简单用法. 关于python mock,网上有很多资料,这里不会讲的特别深,但一定会是实用为主, ...