最近用到了这个功能,要计算一些字符串表达式,如"1 + 3 / 2"等等,就写了这个类。原理很简单,就是用CodeDom动态生成一个包含自定义函数的程序集,再通过反射调用。网上例子极多。我这个类是拿来就可以用的,只需要Copy一下代码就可以直接用,不用读代码
。支持常用数学函数,如Sin,Log等,而且不区分大小写。
using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.VisualBasic;
using System.Reflection;
![]()
namespace Ninputer.Utilities
{
sealed class Evaluator
{
private static CodeDomProvider comp = new VBCodeProvider();
private static CompilerParameters cp = new CompilerParameters();
private static MethodInfo mi;
![]()
public static object Eval(string expression)
{
StringBuilder codeBuilder = new StringBuilder();
![]()
codeBuilder.AppendLine("Imports System");
codeBuilder.AppendLine("Imports System.Math");
codeBuilder.AppendLine("Imports Microsoft.VisualBasic");
codeBuilder.AppendLine();
codeBuilder.AppendLine("Public Module Mode");
codeBuilder.AppendLine(" Public Function Func() As Object");
codeBuilder.AppendLine(" Return " + expression);
codeBuilder.AppendLine(" End Function");
codeBuilder.AppendLine("End Module");
![]()
cp.ReferencedAssemblies.Add("System.dll");
cp.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;
![]()
string code = codeBuilder.ToString();
CompilerResults cr = comp.CompileAssemblyFromSource(cp, code);
![]()
if (cr.Errors.HasErrors)
{
return null;
}
else
{
Assembly a = cr.CompiledAssembly;
Type t = a.GetType("Mode");
//object mode = a.CreateInstance("Mode");
mi = t.GetMethod("Func", BindingFlags.Static | BindingFlags.Public);
return mi.Invoke(null, new object[0]);
}
}
}
}
![]()
用法也非常简单,实际上除了数学表达式,任何含字面量的有效VB表达式都可以执行。
{class Program
![]()
static void Main(string[] args)
{
double a = (double)Evaluator.Eval("sin(0.2) + 5");
Console.WriteLine(a.ToString());
}
}
注意,我使用的是.NET 2.0的语法,使用.NET 1.1 / VS.NET 2003的请用这段代码:
浙公网安备 33010602011771号