C#实现 Eval

时间:2024-11-11 08:33:56

主要是使用 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 ;
}
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 ;
}
}

调用方法很简单: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的方法,最后就是反射的那个方法。