【问题标题】:Change expression delegate body at runtime?在运行时更改表达式委托主体?
【发布时间】:2013-01-14 19:03:25
【问题描述】:

我有这段代码可以生成一个委托,它将 myNumber 乘以 5

ParameterExpression numParam = Expression.Parameter(typeof(int), "num");
ConstantExpression five = Expression.Constant(5, typeof(int));
BinaryExpression numMultiply = Expression.Multiply(numParam,five);

让我们创建委托:

Expression<Func<int, int>> lambda1 =
    Expression.Lambda<Func<int, int>>(
        numMultiply,
        new ParameterExpression[] { numParam });
Console.Write(lambda1.Compile()(4));

现在假设我想将此表达式树更改为 Add 而不是 Multiply
这是新行:

BinaryExpression numAdd = Expression.Add(numParam,five);

但是如何更改 lambda1 以便它现在使用 numAdd 而不是 multiply

【问题讨论】:

  • Expression 是不可变的;你无能为力会改变它。您唯一能做的就是根据您想要的更改创建一个新的Expression,并确保相关变量引用新的Expression

标签: c# .net .net-4.0 expression-trees


【解决方案1】:

您只需构建一个新的并编译它。

Expression<Func<int, int>> lambda1 =
     Expression.Lambda<Func<int, int>>(
         numAdd,
         new ParameterExpression[] { numParam });

来自MSDN page

表达式树应该是不可变的。这意味着如果要修改表达式树,则必须通过复制现有表达式树并替换其中的节点来构建新的表达式树。您可以使用表达式树访问者来遍历现有的表达式树。

“应该是”这个短语有点奇怪,但是当您查看 API 时,您会发现所有相关属性(Body、Left、Right)都是只读的。

【讨论】:

  • 无法修改现有的?
  • 您是否尝试过重新分配numMultiply,然后再次编译表达式?在这种情况下,您当然应该将 numMultiply 重命名为更通用的名称,例如 operation
  • 您可以使用表达式更改事物的行为。不是个人的表达。把它想象成一个字符串。它无法更改,但您可以分配一个新的。
  • 它们是不可变的,我添加了一个链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
  • 2011-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多