主要是使用 CSharpCodeProvider,动态调用来进行返回。
首先会拼接成一个类的一个方法,然后返回这个方法的值。不过,因为还是使用反射,所以效率不高。
public static class StringHelper { private static string prefix = @"using System; public static class DynamicClass { public static double Bomb() { "; public static string postfix = @"}}"; public static double Eval(this string strResult) { if (strResult == "" || strResult == null) { return 0; } string strCode = prefix + "return " + strResult + ";" + postfix; CompilerResults result = null; using (CSharpCodeProvider provider = new CSharpCodeProvider()) { var options = new CompilerParameters(); options.GenerateInMemory = true; result = provider.CompileAssemblyFromSource(options, strCode); if (result.Errors.HasErrors) { var errorMsg = new StringBuilder(); foreach (CompilerError error in result.Errors) { errorMsg.AppendFormat("Line:{0},Column:{1},Content:{2}", error.Line, error.Column, error.ErrorText); } Console.WriteLine(errorMsg.ToString()); } else { Type dynamicClass = result.CompiledAssembly.GetType("DynamicClass"); object obj = dynamicClass.InvokeMember("Bomb", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, null, null, null); return (double)obj; } } return 0; } }
调用方法很简单:Console.WriteLine("1 + 2 + 3".Eval());
或者直接调用 JavaScript 的 Eval
public static object Eval(string s) { Microsoft.JScript.Vsa.VsaEngine ve = Microsoft.JScript.Vsa.VsaEngine.CreateEngine(); return Microsoft.JScript.Eval.JScriptEvaluate(s, ve); }
还可以使用 DataTable 的 Compute进行计算
static DataTable dt = new DataTable(); public static object EvalDataTable(string s) { return dt.Compute(s, null); }
相比较而言,DataTable 更快,其次 JavaScript的方法,最后就是反射的那个方法。