C#动态执行字符串(动态创建代码)
在编写C#程序的时候,有时我们需要动态生成一些代码并执行。然而C#不像JavaScript有一个Eval函数,可以动态的执行代码。所有这些功能都要我们自己去完成。如下是实例。
动态创建代码:
using System;
using System.Data;
using System.Configuration;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection; namespace EvalGuy
{
/// <summary>
/// 本类用来将字符串转为可执行文本并执行
/// 从别处复制,勿随意更改!
/// </summary>
public class Evaluator
{
#region 构造函数
/// <summary>
/// 可执行串的构造函数
/// </summary>
/// <param name="items">
/// 可执行字符串数组
/// </param>
public Evaluator(EvaluatorItem[] items)
{
ConstructEvaluator(items); //调用解析字符串构造函数进行解析
}
/// <summary>
/// 可执行串的构造函数
/// </summary>
/// <param name="returnType">返回值类型</param>
/// <param name="expression">执行表达式</param>
/// <param name="name">执行字符串名称</param>
public Evaluator(Type returnType, string expression, string name)
{
//创建可执行字符串数组
EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) };
ConstructEvaluator(items); //调用解析字符串构造函数进行解析
}
/// <summary>
/// 可执行串的构造函数
/// </summary>
/// <param name="item">可执行字符串项</param>
public Evaluator(EvaluatorItem item)
{
EvaluatorItem[] items = { item };//将可执行字符串项转为可执行字符串项数组
ConstructEvaluator(items); //调用解析字符串构造函数进行解析
}
/// <summary>
/// 解析字符串构造函数
/// </summary>
/// <param name="items">待解析字符串数组</param>
private void ConstructEvaluator(EvaluatorItem[] items)
{
//创建C#编译器实例
ICodeCompiler comp = (new CSharpCodeProvider().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 EvalGuy { \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 = comp.CompileAssemblyFromSource(cp, code.ToString()); 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("EvalGuy._Evaluator"); //通过程序集查找并声明 EvalGuy._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 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)
{
Evaluator eval = new Evaluator(typeof(int), code, staticMethodName);//生成 Evaluator 类的对像
return (int)eval.Evaluate(staticMethodName); //执行并返回整型数据
}
/// <summary>
/// 执行表达式并返回字符串型值
/// </summary>
/// <param name="code">要执行的表达式</param>
/// <returns>运算结果</returns>
static public string EvaluateToString(string code)
{
Evaluator eval = new Evaluator(typeof(string), code, staticMethodName);//生成 Evaluator 类的对像
return (string)eval.Evaluate(staticMethodName); //执行并返回字符串型数据
}
/// <summary>
/// 执行表达式并返回布尔型值
/// </summary>
/// <param name="code">要执行的表达式</param>
/// <returns>运算结果</returns>
static public bool EvaluateToBool(string code)
{
Evaluator eval = new Evaluator(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)
{
Evaluator eval = new Evaluator(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;
}
}
}
调用方法:注意引用EvalGuy命名空间:
Console.WriteLine("Test0: {0}", Evaluator.EvaluateToInteger("(30 + 4) * 2"));
Console.WriteLine("Test1: {0}", Evaluator.EvaluateToString("\"Hello \" + \"There\""));
Console.WriteLine("Test2: {0}", Evaluator.EvaluateToBool("30 == 40"));
Console.WriteLine("Test3: {0}", Evaluator.EvaluateToObject("new DataSet()"));
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")
};
Evaluator eval = new Evaluator(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"));
转自:http://hi.baidu.com/yxw740/item/e4d256f2208590d342c36acc
C#动态执行字符串(动态创建代码)的更多相关文章
- 如何执行字符串的PHP代码
如何执行字符串的PHP代码 最近因项目需要,引出一个议题:如何执行字符串的php代码(php和html混写). 注:传统情况下,php代码存储在文件中,直接运行文件即可.以下讨论的情况是,如果php代 ...
- 第6.3节 Python动态执行之动态编译的compile函数
Python支持动态代码主要三个函数,分别是compile.eval和exec.本节介绍compile函数的语法和相关使用.compile函数用来编译一段字符串的源码,将其编译为字节码或者AST(抽像 ...
- 执行字符串或注释代码段的方法(eval、exec、execfile)
eval:计算字符串中的表达式exec:执行字符串中的语句execfile:用来执行一个文件 需注意的是,exec是一个语句,而eval()和execfile()则是内建built-in函数. 1 2 ...
- (转+整理)C#中动态执行代码
通过微软提供的CSharpCodeProvider,CompilerParameters,CompilerResults等类,可以在运行时,动态执行自己写的代码文件.原理就是把你的代码文件动态编译成e ...
- 动态执行C#代码
using System; using System.CodeDom.Compiler;using System.Collections.Generic;using System.Linq;using ...
- 执行C#动态代码
执行C#动态代码 using System; using System.Data; using System.Configuration; using System.Text; using Syste ...
- Spring Boot 创建定时任务(配合数据库动态执行)
序言:创建定时任务非常简单,主要有两种创建方式:一.基于注解(@Scheduled) 二.基于接口(SchedulingConfigurer). 前者相信大家都很熟悉,但是实际使用中我们往往想从数据库 ...
- mysql 字符串分割 和 动态执行拼接sql
本人以前主要用的是MSSQL,最近项目在使用MYSQL,自己是一个 典型的小白.今天就记录一下 一个mysql存储过程,里面需要分割字符串和 动态执行sql语句. 关于字符串 分割我开始使用 LOCA ...
- 动态执行文本vba代码
动态执行文本vba代码 Public Sub StringExecute(s As String) Dim vbComp As Object Set vbComp = ThisWorkbook.VBP ...
随机推荐
- knockout 学习实例2 text
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Silverlight管理系统源代码(SilverlightOAFlame开发框架主要提供二次开发)
Silverlight OA系统简介 系统功能简介 l 程序界面介绍: 左侧为主菜单,主菜单可以展开和收起,主菜单下面的所有模块都可以在数据库中扩展增加,模块的权限和用户角色挂钩,可以在数据库中创建多 ...
- SonarQube的安装、配置与使用
SonarQube是管理代码质量一个开放平台,可以快速的定位代码中潜在的或者明显的错误,下面将会介绍一下这个工具的安装.配置以及使用. 准备工作: 1.jdk(不再介绍) 2.sonarqube:ht ...
- NHibernate和 FluentNHibernate
NHibernate有两类配置文件,一个是数据库连接配置文件(一般写到程序配置文件里),另一个是数据表和实体的映射文件(实体类.hbm.xml) 开源的框架Fluent NHibernate,有了它, ...
- IntelliJ IDEA内存优化最佳实践
[编者按]本文作者在和同事的一次讨论中发现,对 IntelliJ IDEA 内存采用不同的设置方案,会对 IDE 的速度和响应能力产生不同的影响. Don’t be a Scrooge and giv ...
- java 进程启用远程查看
用jconsole 1.启动脚本增加: JAVA_OPTS="-Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=192.1 ...
- repeat语句
一.repeat语句格式repeat语句用于"重复执行循环体,直到指定的条件为真时为止" repeat语句格式:repeat 语句1; 语句2; -- 语句n;until ...
- OPTIMIZE TABLE的作用--转载
当您的库中删除了大量的数据后,您可能会发现数据文件尺寸并没有减小.这是因为删 除操作后在数据文件中留下碎片所致.Discuz! 在系统数设置界面提供了数据表优化的功能,可以去除删除操作后留下的数据文件 ...
- UIAutomator 编译
环境搭建 1.必备条件: 1.JDK 2.SDK(API高于15) 3.Eclipse(安装ADT插件) 4.ANT(用于编译生成jar) 2.简要步骤: 1.安装JDK并添加环境变 ...
- AbstractQueueSynchronizer
1.AbstractQueuedSynchronizer(以下简称AQS)是Java并发包提供的一个同步基础机制,是并发包中实现Lock和其他同步机制(如:Semaphore.CountDownLat ...