Convert Expression> to Expression>

c# expression-trees lambda

Question

I have a LambdaExpression which is of type Expression<Func<T, string>>. The design of the code currently does not allow me to keep T which means that I am forced to use the slower DynamicInvoke instead of Invoke.

Since I know the type of T I want to convert the expression so that it accepts a T object, allowing me to use Invoke. How?

Here's a good start

class Program
{
    class MyClass
    {
        public string MyProperty => "Foo";
    }

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

    static void Main(string[] args)
    {
        var e1 = GetExpression(t => t.MyProperty);
        var e2 = Expression.Lambda<Func<object, object>>(e1, e1.Parameters);

        object myClass = new MyClass();
        string s1 = (string)e1.Compile().DynamicInvoke(myClass);
        object s2 = e2.Compile().Invoke(myClass);
    }
}

Accepted Answer

The non-expression version would look like

Func<object, object> Convert<T>(Func<T, object> f) {
  return o => f((T)o);
}

This is what you need to do in the expression version as well. You're right, Expression.Convert can do that.

Expression<Func<MyClass, object>> e1 = t => t.MyProperty;
var p = Expression.Parameter(typeof(object));
var e2 = Expression.Lambda<Func<object, object>>(
    Expression.Invoke(e1, Expression.Convert(p, typeof(MyClass))), p);

Note: as @xanatos rightly notes, for converting e.g. Expression<Func<T, int>> to Expression<Func<object, object>>, although C# supports an implicit boxing conversion from int to object, expression trees don't. If this is relevant to the question, another Expression.Convert is needed.



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why