Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert Expression<Func<T, U>> to Expression<Func<object, object>>

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);
    }
}
like image 728
l33t Avatar asked Dec 07 '25 08:12

l33t


1 Answers

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.


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!