【问题标题】:Evaluate expression as string, return object?将表达式评估为字符串,返回对象?
【发布时间】:2011-08-03 07:58:33
【问题描述】:

基本上我有一些代码,当它发生时,我需要设置一些对象等于某个表达式。所有这些“做什么”爵士乐都存储为字符串。所以我解析它,并使用反射来找到我正在做的对象。现在我需要找出如何将值存储到这个对象。问题是该值可能是“1”、“1*(5/2)”或“某个字符串值”。如果我能有像“this.SomeProperty”或“(x > 3 ? 4 : 5)”这样的表达式,那就太酷了。

此外,它存储到的对象可以是字符串、int、double 或至少是 float。

【问题讨论】:

标签: c# reflection runtime compilation


【解决方案1】:

你见过http://ncalc.codeplex.com 吗?

它是可扩展的、快速的(例如有自己的缓存),使您能够通过处理 EvaluateFunction/EvaluateParameter 事件在运行时提供自定义函数和变量。它可以解析的示例表达式:

Expression e = new Expression("Round(Pow(Pi, 2) + Pow([Pi2], 2) + X, 2)"); 

  e.Parameters["Pi2"] = new Expression("Pi * Pi"); 
  e.Parameters["X"] = 10; 

  e.EvaluateParameter += delegate(string name, ParameterArgs args) 
    { 
      if (name == "Pi") 
      args.Result = 3.14; 
    }; 

  Debug.Assert(117.07 == e.Evaluate()); 

它还可以原生处理 unicode 和许多数据类型。如果您想更改语法,它会附带一个 antler 文件。还有一个 fork 支持 MEF 加载新功能。

【讨论】:

    【解决方案2】:

    VS2008 示例包含一个漂亮的 ExpressionParser,它可以用作通用表达式解析器 (VS2008 Samples)。通过一些小的更新和自定义工厂类,我们可以将其变成更具表现力的东西:

    string expression = "(1 + 2)";
    var func = FunctionFactory.Create<int>(expression);
    

    或者:

    expression = "(a * b)";
    var func2 = FunctionFactory.Create<int, int, int>(expression, new[] { "a", "b" });
    

    这些Create 方法的返回类型是Func&lt;&gt; 实例,这意味着我们得到了很好的强类型委托:

    int result = func2(45, 100); // result = 450;
    

    我已将代码推送到gist

    更新:我最近也blogged about this。

    更新 2,另一个例子:

    var person = new Person { Age = 5 };
    string expression = "(Age == 5)";
    var func3 = FunctionFactory.Create<Person, bool>(expression);
    
    bool isFive = func3(person); // Should be true.
    

    【讨论】:

    • 这很漂亮。我不知道 FunctionFactory/ExpressionParser 存在。它仍然涉及手动解析参数的值,但表达式的整体结果是自动化的。
    • @Nick - FunctionFactory 是我在 VS2008 ExpressionParser 类型周围拼凑起来的东西。随意使用和滥用它 :-)
    • 这太棒了。您可以在事先不知道参数列表(即示例中的 a 和 b )的情况下创建表达式吗?就像从表达式字符串中动态推断参数一样?
    • @Justin - 如果不修改 ExpressionParser 以更新包含的用于匹配参数的 ParameterExpression 实例,我不相信它会起作用。我认为的问题是您可能无法区分什么是操作数(您传入)和 this 实例的属性(请参阅上面的更新)。
    猜你喜欢
    • 2015-11-30
    • 2011-06-03
    • 2016-04-24
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多