我需要知道是否有任何库允许我,给定一个表示数学函数的字符串,比如x^2+x+1
,(不关心字符串格式,任何意志为我工作)生成一个代表所述函数的C#func。
答案 0 :(得分:9)
现在使用FLEE(快速轻量级表达评估器)已经有一段时间了,它一直很好用。他们有一个版本,可以维护Silverlight的大部分功能。它旨在完全满足您的要求和更多。
Flee是.NET框架的表达式解析器和评估器。它 允许您计算字符串表达式的值,例如sqrt(a ^ 2 + b ^ 2)在运行时。它使用自定义编译器,强类型表达式语言和轻量级codegen来编译表达式 直接到IL。这意味着表达评估极其重要 快速高效。
根据您评论评估x^2+x+1
的例子(用记事本编写):
public Func<double, double> CreateExpressionForX(string expression)
{
ExpressionContext context = new ExpressionContext();
// Define some variables
context.Variables["x"] = 0.0d;
// Use the variables in the expression
IDynamicExpression e = context.CompileDynamic(expression);
Func<double, double> expressionEvaluator = (double input) =>
{
content.Variables["x"] = input;
var result = (double)e.Evaluate();
return result;
}
return expressionEvaluator;
}
Func<double, double> expression = CreateExpressionForX("x^2 + x + 1");
double result1 = expression(1); //3
double result2 = expression(20.5); //441.75
double result3 = expression(-10.5); //121.75
Func<double, double> expression2 = CreateExpressionForX("3 * x + 10");
double result4 = expression2(1); //13
double result5 = expression2(20.5); //71.5
double result6 = expression2(-10.5); //-21.5
答案 1 :(得分:4)
看看Roslyn API。它允许您在运行时编译字符串
答案 2 :(得分:2)
您可以使用 CSharpCodeProvider 类将代码编译到文件/程序集并动态加载已编译的程序集。使用程序中的编译器描述here。这个Stackoverflow questions显示了如何加载已编译的程序集。请记住,您需要将函数包装在类中以便稍后加载并执行它。
或者,您可以使用CS-Script进行脏程序集编译,加载和执行作业。
答案 3 :(得分:1)
您可以使用CodeDOM动态编译类型,关于此,here您可以找到一个简单的代码编写的流畅界面,例如:
var compileUnit = new FluentCodeCompileUnit()
.Namespace("Sample1")
.Class("Program")
.Method(MemberAttributes.Public | MemberAttributes.Static, "Main").Parameter(typeof(string[]), "args")
.CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Hello Fluent CodeDom"))
.EndMethod
.Method(MemberAttributes.Public | MemberAttributes.Static, "Linq2CodeDomSupport").Parameter(typeof(string[]), "args")
.Stmt(ExprLinq.Expr(() => Console.WriteLine("Hello Linq2CodeDOM")))
.Declare(typeof(int), "random", ExprLinq.Expr(() => new Random().Next(10)))
.If((int random) => random <= 5)
.Stmt(ExprLinq.Expr(() => Console.WriteLine("Smaller or equal to 5.")))
.Else
.Stmt(ExprLinq.Expr(() => Console.WriteLine("Bigger than 5.")))
.EndIf
.EndMethod
.EndClass
.EndNamespace
.EndFluent();
var assembly = Helper.CodeDomHelper.CompileInMemory(compileUnit);
assembly.GetType("Sample1.Program").GetMethod("Main").Invoke(null, new object[] { null });
我将在CodePlex上发布一个更好的流畅接口API,它将在RTM中发布时使用Roslyn。
答案 4 :(得分:0)
This看起来很不错。当然,它也可以通过使用Expression Trees和从字符串到表达式的解析来解决,以后可以编译(在运行时)并执行。