转:将字符串或表达式直接转为C#可执行代码的办法

原文地址:http://blog.csdn.net/qwlovedzm/article/details/6292147

近日有个项目有不少的计算公式,而且要求能定制,如何能将字符串或表达式直接转为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.  
  9. namespace SSEC.Math 
  10.     /// <summary>    
  11.     /// 本类用来将字符串转为可执行文本并执行    
  12.     /// </summary>    
  13.     publicclass MyEvaluator 
  14.     { 
  15.         #region 构造函数 
  16.  
  17.         /// <summary>    
  18.         /// 可执行串的构造函数    
  19.         /// </summary>    
  20.         /// <param name="items">    
  21.         /// 可执行字符串数组    
  22.         /// </param>    
  23.         public MyEvaluator(EvaluatorItem[] items) 
  24.         { 
  25.             ConstructEvaluator(items);      //调用解析字符串构造函数进行解析    
  26.         } 
  27.  
  28.         /// <summary>    
  29.         /// 可执行串的构造函数    
  30.         /// </summary>    
  31.         /// <param name="returnType">返回值类型</param>    
  32.         /// <param name="expression">执行表达式</param>    
  33.         /// <param name="name">执行字符串名称</param>    
  34.         public MyEvaluator(Type returnType, string expression, string name) 
  35.         { 
  36.             //创建可执行字符串数组    
  37.             EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) }; 
  38.             ConstructEvaluator(items);      //调用解析字符串构造函数进行解析    
  39.         } 
  40.  
  41.         /// <summary>    
  42.         /// 可执行串的构造函数    
  43.         /// </summary>    
  44.         /// <param name="item">可执行字符串项</param>    
  45.         public MyEvaluator(EvaluatorItem item) 
  46.         { 
  47.             EvaluatorItem[] items = { item };//将可执行字符串项转为可执行字符串项数组    
  48.             ConstructEvaluator(items);      //调用解析字符串构造函数进行解析    
  49.         } 
  50.  
  51.         /// <summary>    
  52.         /// 解析字符串构造函数    
  53.         /// </summary>    
  54.         /// <param name="items">待解析字符串数组</param>    
  55.         privatevoid ConstructEvaluator(EvaluatorItem[] items) 
  56.         { 
  57.             //创建C#编译器实例 
  58.             CodeDomProvider provider = CodeDomProvider.CreateProvider("C#"); 
  59.              
  60.             //过时了 
  61.             //ICodeCompiler comp = provider.CreateCompiler(); 
  62.              
  63.             //编译器的传入参数    
  64.             CompilerParameters cp = new CompilerParameters(); 
  65.             cp.ReferencedAssemblies.Add("system.dll");              //添加程序集 system.dll 的引用    
  66.             cp.ReferencedAssemblies.Add("system.data.dll");         //添加程序集 system.data.dll 的引用    
  67.             cp.ReferencedAssemblies.Add("system.xml.dll");          //添加程序集 system.xml.dll 的引用    
  68.             cp.GenerateExecutable = false;                          //不生成可执行文件    
  69.             cp.GenerateInMemory = true;                             //在内存中运行    
  70.  
  71.             StringBuilder code = new StringBuilder();               //创建代码串    
  72.             /* 
  73.              *  添加常见且必须的引用字符串 
  74.              */ 
  75.             code.Append("using System; /n"); 
  76.             code.Append("using System.Data; /n"); 
  77.             code.Append("using System.Data.SqlClient; /n"); 
  78.             code.Append("using System.Data.OleDb; /n"); 
  79.             code.Append("using System.Xml; /n"); 
  80.  
  81.             code.Append("namespace SSEC.Math { /n");                  //生成代码的命名空间为EvalGuy,和本代码一样    
  82.  
  83.             code.Append("  public class _Evaluator { /n");          //产生 _Evaluator 类,所有可执行代码均在此类中运行    
  84.             foreach (EvaluatorItem item in items)               //遍历每一个可执行字符串项    
  85.             { 
  86.                 code.AppendFormat("    public {0} {1}() ",          //添加定义公共函数代码    
  87.                                   item.ReturnType.Name,             //函数返回值为可执行字符串项中定义的返回值类型    
  88.                                   item.Name);                       //函数名称为可执行字符串项中定义的执行字符串名称    
  89.                 code.Append("{ ");                                  //添加函数开始括号    
  90.                 code.AppendFormat("return ({0});", item.Expression);//添加函数体,返回可执行字符串项中定义的表达式的值    
  91.                 code.Append("}/n");                                 //添加函数结束括号    
  92.             } 
  93.             code.Append("} }");                                 //添加类结束和命名空间结束括号    
  94.  
  95.             //得到编译器实例的返回结果    
  96.             CompilerResults cr = provider.CompileAssemblyFromSource(cp, code.ToString());//comp 
  97.  
  98.             if (cr.Errors.HasErrors)                            //如果有错误    
  99.             { 
  100.                 StringBuilder error = new StringBuilder();          //创建错误信息字符串    
  101.                 error.Append("编译有错误的表达式: ");                //添加错误文本    
  102.                 foreach (CompilerError err in cr.Errors)            //遍历每一个出现的编译错误    
  103.                 { 
  104.                     error.AppendFormat("{0}/n", err.ErrorText);     //添加进错误文本,每个错误后换行    
  105.                 } 
  106.                 thrownew Exception("编译错误: " + error.ToString());//抛出异常    
  107.             } 
  108.             Assembly a = cr.CompiledAssembly;                       //获取编译器实例的程序集    
  109.             _Compiled = a.CreateInstance("SSEC.Math._Evaluator");     //通过程序集查找并声明 SSEC.Math._Evaluator 的实例    
  110.         } 
  111.         #endregion 
  112.         #region 公有成员 
  113.         /// <summary>    
  114.         /// 执行字符串并返回整型值    
  115.         /// </summary>    
  116.         /// <param name="name">执行字符串名称</param>    
  117.         /// <returns>执行结果</returns>    
  118.         publicint EvaluateInt(string name) 
  119.         { 
  120.             return (int)Evaluate(name); 
  121.         } 
  122.         /// <summary>    
  123.         /// 执行字符串并返回双精度值    
  124.         /// </summary>    
  125.         /// <param name="name">执行字符串名称</param>    
  126.         /// <returns>执行结果</returns>    
  127.         publicdouble EvaluateDouble(string name) 
  128.         { 
  129.             return (double)Evaluate(name); 
  130.         } 
  131.         /// <summary>    
  132.         /// 执行字符串并返回长整型数值    
  133.         /// </summary>    
  134.         /// <param name="name">执行字符串名称</param>    
  135.         /// <returns>执行结果</returns>    
  136.         publiclong EvaluateLong(string name) 
  137.         { 
  138.             return (long)Evaluate(name); 
  139.         } 
  140.         /// <summary>    
  141.         /// 执行字符串并返回十进制数值    
  142.         /// </summary>    
  143.         /// <param name="name">执行字符串名称</param>    
  144.         /// <returns>执行结果</returns>    
  145.         publicdecimal EvaluateDecimal(string name) 
  146.         { 
  147.             return (decimal)Evaluate(name); 
  148.         } 
  149.         /// <summary>    
  150.         /// 执行字符串并返回字符串型值    
  151.         /// </summary>    
  152.         /// <param name="name">执行字符串名称</param>    
  153.         /// <returns>执行结果</returns>    
  154.         publicstring EvaluateString(string name) 
  155.         { 
  156.             return (string)Evaluate(name); 
  157.         } 
  158.         /// <summary>    
  159.         /// 执行字符串并返回布尔型值    
  160.         /// </summary>    
  161.         /// <param name="name">执行字符串名称</param>    
  162.         /// <returns>执行结果</returns>    
  163.         publicbool EvaluateBool(string name) 
  164.         { 
  165.             return (bool)Evaluate(name); 
  166.         } 
  167.         /// <summary>    
  168.         /// 执行字符串并返 object 型值    
  169.         /// </summary>    
  170.         /// <param name="name">执行字符串名称</param>    
  171.         /// <returns>执行结果</returns>    
  172.         publicobject Evaluate(string name) 
  173.         { 
  174.             MethodInfo mi = _Compiled.GetType().GetMethod(name);//获取 _Compiled 所属类型中名称为 name 的方法的引用    
  175.             return mi.Invoke(_Compiled, null);                  //执行 mi 所引用的方法    
  176.         } 
  177.         #endregion 
  178.         #region 静态成员 
  179.         /// <summary>    
  180.         /// 执行表达式并返回整型值    
  181.         /// </summary>    
  182.         /// <param name="code">要执行的表达式</param>    
  183.         /// <returns>运算结果</returns>    
  184.         staticpublicint EvaluateToInteger(string code) 
  185.         { 
  186.             MyEvaluator eval = new MyEvaluator(typeof(int), code, staticMethodName);//生成 Evaluator 类的对像    
  187.             return (int)eval.Evaluate(staticMethodName);                        //执行并返回整型数据    
  188.         } 
  189.         /// <summary>    
  190.         /// 执行表达式并返回双精度值    
  191.         /// </summary>    
  192.         /// <param name="name">执行字符串名称</param>    
  193.         /// <returns>执行结果</returns>    
  194.         staticpublicdouble EvaluateToDouble(string code) 
  195.         { 
  196.             MyEvaluator eval = new MyEvaluator(typeof(double), code, staticMethodName);//生成 Evaluator 类的对像    
  197.             return (double)eval.Evaluate(staticMethodName);  
  198.         } 
  199.         /// <summary>    
  200.         /// 执行表达式并返回长整型数值    
  201.         /// </summary>    
  202.         /// <param name="name">执行字符串名称</param>    
  203.         /// <returns>执行结果</returns>    
  204.         staticpubliclong EvaluateToLong(string code) 
  205.         { 
  206.             MyEvaluator eval = new MyEvaluator(typeof(long), code, staticMethodName);//生成 Evaluator 类的对像    
  207.             return (long)eval.Evaluate(staticMethodName);  
  208.         } 
  209.         /// <summary>    
  210.         /// 执行表达式并返回十进制数值    
  211.         /// </summary>    
  212.         /// <param name="name">执行字符串名称</param>    
  213.         /// <returns>执行结果</returns>    
  214.         staticpublicdecimal EvaluateToDecimal(string code) 
  215.         { 
  216.             MyEvaluator eval = new MyEvaluator(typeof(decimal), code, staticMethodName);//生成 Evaluator 类的对像    
  217.             return (decimal)eval.Evaluate(staticMethodName);  
  218.         } 
  219.         /// <summary>    
  220.         /// 执行表达式并返回字符串型值    
  221.         /// </summary>    
  222.         /// <param name="code">要执行的表达式</param>    
  223.         /// <returns>运算结果</returns>    
  224.         staticpublicstring EvaluateToString(string code) 
  225.         { 
  226.             MyEvaluator eval = new MyEvaluator(typeof(string), code, staticMethodName);//生成 Evaluator 类的对像    
  227.             return (string)eval.Evaluate(staticMethodName);                     //执行并返回字符串型数据    
  228.         } 
  229.         /// <summary>    
  230.         /// 执行表达式并返回布尔型值    
  231.         /// </summary>    
  232.         /// <param name="code">要执行的表达式</param>    
  233.         /// <returns>运算结果</returns>    
  234.         staticpublicbool EvaluateToBool(string code) 
  235.         { 
  236.             MyEvaluator eval = new MyEvaluator(typeof(bool), code, staticMethodName);//生成 Evaluator 类的对像    
  237.             return (bool)eval.Evaluate(staticMethodName);                       //执行并返回布尔型数据    
  238.         } 
  239.         /// <summary>    
  240.         /// 执行表达式并返回 object 型值    
  241.         /// </summary>    
  242.         /// <param name="code">要执行的表达式</param>    
  243.         /// <returns>运算结果</returns>    
  244.         staticpublicobject EvaluateToObject(string code) 
  245.         { 
  246.             MyEvaluator eval = new MyEvaluator(typeof(object), code, staticMethodName);//生成 Evaluator 类的对像    
  247.             return eval.Evaluate(staticMethodName);                             //执行并返回 object 型数据    
  248.         } 
  249.         #endregion 
  250.         #region 私有成员 
  251.         /// <summary>    
  252.         /// 静态方法的执行字符串名称    
  253.         /// </summary>    
  254.         privateconststring staticMethodName = "__foo"
  255.         /// <summary>    
  256.         /// 用于动态引用生成的类,执行其内部包含的可执行字符串    
  257.         /// </summary>    
  258.         object _Compiled = null
  259.         #endregion 
  260.     } 
  261.  
  262.  
  263.     /// <summary>    
  264.     /// 可执行字符串项(即一条可执行字符串)    
  265.     /// </summary>    
  266.     publicclass EvaluatorItem 
  267.     { 
  268.         /// <summary>    
  269.         /// 返回值类型    
  270.         /// </summary>    
  271.         public Type ReturnType; 
  272.         /// <summary>    
  273.         /// 执行表达式    
  274.         /// </summary>    
  275.         publicstring Expression; 
  276.         /// <summary>    
  277.         /// 执行字符串名称    
  278.         /// </summary>    
  279.         publicstring Name; 
  280.         /// <summary>    
  281.         /// 可执行字符串项构造函数    
  282.         /// </summary>    
  283.         /// <param name="returnType">返回值类型</param>    
  284.         /// <param name="expression">执行表达式</param>    
  285.         /// <param name="name">执行字符串名称</param>    
  286.         public EvaluatorItem(Type returnType, string expression, string name) 
  287.         { 
  288.             ReturnType = returnType; 
  289.             Expression = expression; 
  290.             Name = name; 
  291.         } 
  292.     } 

 

 

下面是测试类:

  1. class Test 
  2.     { 
  3.         /// <summary> 
  4.         /// The main entry point for the application. 
  5.         /// </summary> 
  6.         [STAThread] 
  7.         staticvoid Main(string[] args) 
  8.         { 
  9.             Console.WriteLine("Test0: {0}", MyEvaluator.EvaluateToInteger("(30 + 4) * 2")); 
  10.             Console.WriteLine("Test1: {0}", MyEvaluator.EvaluateToString("/"Hello /" + /"There/"")); 
  11.             Console.WriteLine("Test2: {0}", MyEvaluator.EvaluateToBool("30 == 40")); 
  12.             Console.WriteLine("Test3: {0}", MyEvaluator.EvaluateToObject("new DataSet()")); 
  13.             Console.WriteLine("Test4: {0}", MyEvaluator.EvaluateToDouble("(12.4+2.2)*0.4")); 
  14.             Console.WriteLine("Test5: {0}", MyEvaluator.EvaluateToLong("(12+1000)*1000")); 
  15.             Console.WriteLine("Test6: {0}", MyEvaluator.EvaluateToString("/"double max==/"+double.MaxValue"));//decimal.MaxValue+/",/"+ 
  16.              
  17.  
  18.             EvaluatorItem[] items = { 
  19.                                     new EvaluatorItem(typeof(int), "(30 + 4) * 2", "GetNumber"), 
  20.                                     new EvaluatorItem(typeof(string), "/"Hello /" + /"There/"", "GetString"), 
  21.                                     new EvaluatorItem(typeof(bool), "30 == 40", "GetBool"), 
  22.                                     new EvaluatorItem(typeof(object), "new DataSet()", "GetDataSet"
  23.                                     }; 
  24.  
  25.             MyEvaluator eval = new MyEvaluator(items); 
  26.             Console.WriteLine("TestStatic0: {0}", eval.EvaluateInt("GetNumber")); 
  27.             Console.WriteLine("TestStatic1: {0}", eval.EvaluateString("GetString")); 
  28.             Console.WriteLine("TestStatic2: {0}", eval.EvaluateBool("GetBool")); 
  29.             Console.WriteLine("TestStatic3: {0}", eval.Evaluate("GetDataSet")); 
  30.             Console.ReadLine(); 
  31.         } 
  32.     } 

 

 

经测试,想要的结果终于出来了。

posted @ 2013-04-27 17:27  wadeheng  阅读(1268)  评论(0编辑  收藏  举报