是否有用于解析字符串以创建 C# 函数的工具
本文关键字:创建 函数 工具 字符串 用于 是否 | 更新日期: 2023-09-27 18:36:02
我需要知道是否有任何库允许我,给定一个表示数学函数的某个字符串,比如说,x^2+x+1
,(不关心字符串格式如何,任何对我有用)生成一个表示所述函数的 C# func。
使用 FLEE(快速轻量级表达式计算器)已经有一段时间了,它一直工作得很好。 他们有一个版本,也维护了Silverlight的大部分功能。 它旨在满足您的要求,甚至更多。
http://flee.codeplex.com/
Flee 是 .NET 框架的表达式解析器和计算器。它 允许您计算字符串表达式的值,例如 sqrt(a^2 + b^2) 在运行时。它使用自定义编译器、强类型表达式语言和轻量级代码生成来编译表达式 直接到伊利诺伊州。这意味着表达评估非常 快速高效。
从您的评论中给出您的示例来评估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
看看 Roslyn API。它将允许您在运行时编译字符串
可以使用 CSharpCodeProvider 类将代码编译为文件/程序集,并动态加载已编译的程序集。此处介绍了使用程序中的编译器。此 Stackoverflow 问题演示如何加载已编译的程序集。请记住,您需要将函数包装在类中,以便稍后加载和执行它。
或者,您可以使用 CS-Script 执行脏程序集编译、加载和执行作业。
你可以使用 CodeDOM 来动态编译一个类型,关于这个,在这里你可以找到一个流畅的接口来简单地编写代码,例如:
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。
这看起来是一个很好的解决方案。当然,也可以通过使用表达式树和从字符串到表达式的解析来解决,稍后可以编译(在运行时)并执行表达式。