原文地址:http://blog.csdn.net/qwlovedzm/article/details/6292147
近日有个项目有不少的计算公式,而且要求能定制,如何能将字符串或表达式直接转为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
- {
-
-
-
- publicclass MyEvaluator
- {
- #region 构造函数
-
-
-
-
-
-
-
- public MyEvaluator(EvaluatorItem[] items)
- {
- ConstructEvaluator(items);
- }
-
-
-
-
-
-
-
- public MyEvaluator(Type returnType, string expression, string name)
- {
-
- EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) };
- ConstructEvaluator(items);
- }
-
-
-
-
-
- public MyEvaluator(EvaluatorItem item)
- {
- EvaluatorItem[] items = { item };
- ConstructEvaluator(items);
- }
-
-
-
-
-
- privatevoid ConstructEvaluator(EvaluatorItem[] items)
- {
-
- CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
-
-
-
-
-
- CompilerParameters cp = new CompilerParameters();
- cp.ReferencedAssemblies.Add("system.dll");
- cp.ReferencedAssemblies.Add("system.data.dll");
- cp.ReferencedAssemblies.Add("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");
-
- code.Append(" public class _Evaluator { /n");
- 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());
-
- if (cr.Errors.HasErrors)
- {
- StringBuilder error = new StringBuilder();
- error.Append("编译有错误的表达式: ");
- foreach (CompilerError err in cr.Errors)
- {
- error.AppendFormat("{0}/n", err.ErrorText);
- }
- thrownew Exception("编译错误: " + error.ToString());
- }
- Assembly a = cr.CompiledAssembly;
- _Compiled = a.CreateInstance("SSEC.Math._Evaluator");
- }
- #endregion
-
- #region 公有成员
-
-
-
-
-
- publicint EvaluateInt(string name)
- {
- return (int)Evaluate(name);
- }
-
-
-
-
-
- publicdouble EvaluateDouble(string name)
- {
- return (double)Evaluate(name);
- }
-
-
-
-
-
- publiclong EvaluateLong(string name)
- {
- return (long)Evaluate(name);
- }
-
-
-
-
-
- publicdecimal EvaluateDecimal(string name)
- {
- return (decimal)Evaluate(name);
- }
-
-
-
-
-
- publicstring EvaluateString(string name)
- {
- return (string)Evaluate(name);
- }
-
-
-
-
-
- publicbool EvaluateBool(string name)
- {
- return (bool)Evaluate(name);
- }
-
-
-
-
-
- publicobject Evaluate(string name)
- {
- MethodInfo mi = _Compiled.GetType().GetMethod(name);
- return mi.Invoke(_Compiled, null);
- }
- #endregion
-
- #region 静态成员
-
-
-
-
-
- staticpublicint EvaluateToInteger(string code)
- {
- MyEvaluator eval = new MyEvaluator(typeof(int), code, staticMethodName);
- return (int)eval.Evaluate(staticMethodName);
- }
-
-
-
-
-
- staticpublicdouble EvaluateToDouble(string code)
- {
- MyEvaluator eval = new MyEvaluator(typeof(double), code, staticMethodName);
- return (double)eval.Evaluate(staticMethodName);
- }
-
-
-
-
-
- staticpubliclong EvaluateToLong(string code)
- {
- MyEvaluator eval = new MyEvaluator(typeof(long), code, staticMethodName);
- return (long)eval.Evaluate(staticMethodName);
- }
-
-
-
-
-
- staticpublicdecimal EvaluateToDecimal(string code)
- {
- MyEvaluator eval = new MyEvaluator(typeof(decimal), code, staticMethodName);
- return (decimal)eval.Evaluate(staticMethodName);
- }
-
-
-
-
-
- staticpublicstring EvaluateToString(string code)
- {
- MyEvaluator eval = new MyEvaluator(typeof(string), code, staticMethodName);
- return (string)eval.Evaluate(staticMethodName);
- }
-
-
-
-
-
- staticpublicbool EvaluateToBool(string code)
- {
- MyEvaluator eval = new MyEvaluator(typeof(bool), code, staticMethodName);
- return (bool)eval.Evaluate(staticMethodName);
- }
-
-
-
-
-
- staticpublicobject EvaluateToObject(string code)
- {
- MyEvaluator eval = new MyEvaluator(typeof(object), code, staticMethodName);
- return eval.Evaluate(staticMethodName);
- }
- #endregion
-
- #region 私有成员
-
-
-
- privateconststring staticMethodName = "__foo";
-
-
-
- object _Compiled = null;
- #endregion
- }
-
-
-
-
-
- publicclass EvaluatorItem
- {
-
-
-
- public Type ReturnType;
-
-
-
- publicstring Expression;
-
-
-
- publicstring Name;
-
-
-
-
-
-
- public EvaluatorItem(Type returnType, string expression, string name)
- {
- ReturnType = returnType;
- Expression = expression;
- Name = name;
- }
- }
- }
下面是测试类:
- class Test
- {
-
-
-
- [STAThread]
- staticvoid 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"));
-
-
- 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();
- }
- }
经测试,想要的结果终于出来了。
|
请发表评论