http://blog.csdn.net/hsrzq/article/details/4456361
在编写C#程序的时候,有时我们需要动态生成一些代码并执行。然而C#不像JavaScript有一个Eval函数,可以动态的执行代码。所有这些功能都要我们自己去完成,在参考了许多文章及代码之后,觉得http://www.codeproject.com/csharp/runtime_eval.asp最为有用。于是我将其添加注释后放于此处供大家学习。
- 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;
- }
- }
- }
调用方法:
- 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"));
我已经将它封装成DLL控件,下载地址http://download.csdn.net/source/1582699
记得一定要引用EvalGuy命名空间!