【问题标题】:Is there a tool for parsing a string to create a C# func?是否有用于解析字符串以创建 C# func 的工具?
【发布时间】:2012-06-07 12:33:14
【问题描述】:

我需要知道是否有任何库可以让我在给定表示数学函数的某个字符串的情况下,例如x^2+x+1,(不要关心字符串格式如何,任何都可以me) 生成一个表示所述函数的 C# 函数。

【问题讨论】:

标签: c# string parsing function string-parsing


【解决方案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

【讨论】:

    【解决方案2】:

    使用 FLEE(快速轻量级表达式评估器)已有一段时间了,它运行良好。他们的版本也为 Silverlight 保留了大部分功能。它的设计几乎完全符合您的要求,甚至更多。

    http://flee.codeplex.com/

    Flee 是 .NET 框架的表达式解析器和求值器。它 允许您计算字符串表达式的值,例如 sqrt(a^2 + b^2) 在运行时。它使用自定义编译器、强类型表达式语言和轻量级代码生成来编译表达式 直接去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
    

    【讨论】:

      【解决方案3】:

      您可以使用 CSharpCodeProvider 类将代码编译为文件/程序集并动态加载编译后的程序集。在您的程序中使用编译器在here 中进行了描述。这个Stackoverflow questions 展示了如何加载已编译的程序集。请记住,您需要将函数包装在一个类中以便稍后加载和执行它。

      您也可以使用CS-Script 来完成脏程序集的编译、加载和执行工作。

      【讨论】:

      • 我的意思是解析数学函数以在 C# 中运行。
      • 您本可以在原始问题中提到这一点。这仍然可以用表达式树很容易地解决,但我想 Chris Sinclair 提供的工具会做得很好。
      【解决方案4】:

      This 看起来是一个不错的解决方案。当然,也可以通过Expression Trees的使用和从字符串到表达式的解析来解决,稍后可以编译(在运行时)并执行。

      【讨论】:

      • 我的意思是解析数学函数以在 C# 中运行。
      【解决方案5】:

      看看Roslyn API。它将允许您在运行时编译字符串

      【讨论】:

      • 很好,尽管据我所知,它离真正的工作/完成还很远。看看整个概念将如何与我们使用 c#/vb.net 的方式相结合会很有趣
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-21
      • 1970-01-01
      相关资源
      最近更新 更多