【问题标题】:Use value of property expression inside expression tree在表达式树中使用属性表达式的值
【发布时间】:2017-04-07 23:08:27
【问题描述】:

考虑像t => t.MyProperty 这样的属性表达式,其中t 的类型为MyClass。如何在执行方法调用的新表达式中使用此属性表达式?

C#

class MyClass
{
    public string MyProperty { get; set; }
}

static void Foo(string foo)
{   
}

LambdaExpression GetExpression(Expression<Func<MyClass, object>> expr)
{
    return expr;
}

var myClass = new MyClass();
Foo(myClass.MyProperty);

现在用表达式...?

var expr = GetExpression(m => m.MyProperty);
var mi = typeof(Program).GetMethod(nameof(Program.Foo),
    BindingFlags.Public | BindingFlags.Static);

var myClass = new MyClass();
// Now what??
// var call = Expression.Call(mi, ???expr??);
// var invoke = Expression.Invoke(call, fooParameter);

我想使用expr 的结果并在对Foo 的调用中使用它。我知道我可以分两步执行此操作,我调用expr.Compile().DynamicInvoke(myClass) 来获取价值,但这不是我在这里要求的。

我想构建一个表达式,它接受一个属性 getter 表达式,然后调用表达式)Foo(result。我不知道如何将表达式用作方法调用的参数。

【问题讨论】:

  • 根本不清楚您要达到的目标。方法Foo 采用string;你的Expression 产生一个object。您想使用什么表达式作为调用什么方法的参数?
  • 如果我理解了,你应该就可以使用Expression.Call(mi, Expression.Invoke( ... )) ?
  • 这是挑战的一部分。可能需要转换。很清楚我想要达到的目标。对于给定的MyClass 对象 M,我想调用 Foo(M.MyProperty)。输入是由上述GetExpression 方法生成的表达式。
  • 明白了;给我一秒钟...
  • @l33t Foo 采用 string,而 Expression 产生 object。您是否想要在两者之间进行简单转换,因为您知道 object 实际上是string

标签: c# lambda expression-trees


【解决方案1】:

有两种方法可以做到这一点,具体取决于复杂性。在这种情况下,我们可以重用内部表达式中的参数——向外冒泡;我们通过丢弃旧的 lambda 来做到这一点,只使用 .Body.Parameters。例如:

var call = Expression.Lambda<Action<MyClass>>(
    Expression.Call(mi, expr.Body), expr.Parameters);

var myClass = new MyClass { MyProperty = "yay!" };
call.Compile().Invoke(myClass);

另一种方法是在内部 lambda 上使用Invoke

var outerParameter = Expression.Parameter(typeof(MyClass));
var typed = Expression.Convert(Expression.Invoke(expr, outerParameter), typeof(string));
var call = Expression.Lambda<Action<MyClass>>(Expression.Call(mi, typed), outerParameter);

第二种形式(Invoke)在您不能方便地控制两个地方的参数时很有用 - 或者,例如,您有多个带有 不同 参数实例的内部表达式。

【讨论】:

  • 哇。拯救了我的一天。谢谢!
  • 第二种方法在我的情况下实际上非常有用。谢谢。
  • @l33t 如果您愿意,实际上还有第三种选择:使用自定义 ExpressionVisitor 将一个表达式的所有内容替换为另一个表达式 - 例如,将内部参数替换为外部参数,但适用于任何表达。如果您愿意,可以提供示例。
猜你喜欢
  • 2022-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多