Consider a property expression like t => t.MyProperty
where t
is of type MyClass
. How can I use this property expression inside a new expression where I perform a method call?
Pure 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);
Now with expressions...?
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);
I want to use the result of expr
and use that in the call to Foo
. I know I can do this in two steps, where I call expr.Compile().DynamicInvoke(myClass)
to get the value, but that is not what I'm asking for here.
I want to build an expression that takes a property getter expression and then performs a call to Foo(
result of expression)
. I cannot figure out how to use the expression as a parameter to the method call.
There's two ways of doing this, depending on the complexity. In this case, we can re-use the parameter from the inner expression - bubbling it outwards; we do this by discarding our old lambda, just using the .Body
and .Parameters
. For example:
var call = Expression.Lambda<Action<MyClass>>(
Expression.Call(mi, expr.Body), expr.Parameters);
var myClass = new MyClass { MyProperty = "yay!" };
call.Compile().Invoke(myClass);
The other way is to use Invoke
on the inner lambda:
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);
The second form (Invoke
) is useful when you can't conveniently control the parameters in the two places - or where, for example, you have multiple inner expressions with different parameter instances.