我正在创建树状结构,允许用户定义数学运算。用户选择功能(比如Add),并且在节点的叶子中(至少两个,但可以更多)用户可以指定参数(值或其他功能)。我认为使用表达式是一个好主意,但似乎表达式只支持二进制操作。我想知道是否有一些方法来创建具有两个以上参数的Add函数表达式。例如,如果我写:
Expression<Func<double, double, double, double>> e = (x, y, z) => x + y + z;
我得到树:[(x + y)+ z],所以显然有某种解析器。
如果我无法使用,我可能会编写一些逻辑来手动创建子树。或者也许有更好的方法?任何帮助将不胜感激。
以下是我的简单节点类:
abstract class Node
{
public abstract void PrepareExpression();
public Expression Expr { get; set; }
public string Name { get; set; }
public IList<Node> InnerNodes { get; set; }
protected Node()
{
InnerNodes = new List<Node>();
}
}
class AddFunction : Node
{
public AddFunction()
{
Name = String.Format("Sum_{0}", Guid.NewGuid());
}
public override void PrepareExpression()
{
var exprParams = new List<ParameterExpression>(InnerNodes.Count);
foreach (var node in InnerNodes)
{
node.PrepareExpression();
}
var binaryExpression = Expression.AddChecked(InnerNodes[0].Expr, InnerNodes[1].Expr);
Expr = binaryExpression;
}
}
class ValueArgument : Node
{
public double Value { get; set; }
public ValueArgument(double value)
{
Name = String.Format("Val_{0}", Guid.NewGuid());
Value = value;
}
public override void PrepareExpression()
{
var constantExpression = Expression.Constant(Value, typeof(double));
Expr = constantExpression;
}
}
评估整棵树:
rootNode.PrepareExpression();
var expr = Expression.Lambda<Func<double>>(rootNode.Expr);
var exprCom = expr.Compile();
var result = exprCom.Invoke();
答案 0 :(得分:2)
您的示例中的表达式是二进制的,这就是您所需要的。只需多次应用它们。您自己提供的示例:
x + y + z = (x + y) + z
对应于二元运算符的两个应用程序,即两个二进制表达式:
Add( Add(x, y), z)
这里有两个主要观察结果:
Add
的结果本身就是一个表达式,因此它可以是另一个Add
操作的操作数答案 1 :(得分:0)
您是否希望将字符串解析为表达式?如果是这样,不要重新发明轮子。查看Dijkstra的Shunting Yard algorithm。