考虑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(
结果表达式)
的调用。我无法弄清楚如何将表达式用作方法调用的参数。
答案 0 :(得分:3)
根据复杂程度,有两种方法可以做到这一点。在这种情况下,我们可以重复使用来自内部表达式的参数 - 向外冒泡;我们通过丢弃旧的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
)在您无法方便地控制两个地方的参数时很有用 - 或者,例如,您有多个内部表达式,其中不同的参数实例