是否有解析字符串以创建C#func的工具?

时间:2012-06-02 17:07:22

标签: c# string parsing function string-parsing

我需要知道是否有任何库允许我,给定一个表示数学函数的字符串,比如x^2+x+1,(不关心字符串格式,任何意志为我工作)生成一个代表所述函数的C#func。

5 个答案:

答案 0 :(得分:9)

现在使用FLEE(快速轻量级表达评估器)已经有一段时间了,它一直很好用。他们有一个版本,可以维护Silverlight的大部分功能。它旨在完全满足您的要求和更多。

http://flee.codeplex.com/

  

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和从字符串到表达式的解析来解决,以后可以编译(在运行时)并执行。