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);
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With