Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get actual return type from a Expression<Func<T, object>> instance

I have a method that accepts a Expression<Func<T, object>> instance. I want to get at the actual data type being returned by a specific expression instance, rather than object.

I can get it to work for direct property references, so if I pass in the expression x => x.IntegerProperty I can get a Type reference for an integer. This approach requires converting it to a MemberExpression.

However, I can't get it to work for arbitrary expressions. For instance, if the expression is x => x.IntegerProperty.ToString() I want to get a Type reference for a string. I can't compile this to a MemberExpression, and if I just .Compile() it and check the return type I get "object".

How can I look at the specific expression instance and derive the actual return type?

like image 841
Seth Petry-Johnson Avatar asked Nov 08 '11 18:11

Seth Petry-Johnson


2 Answers

While not impossible, this is particularly difficult. It would require walking the expression tree and doing some potentially complex logic. For example, what would you want to see if I passed in the following expression?

Func<bool, object> expr = switch => switch ? 1 : "False";

This method could either return an int or a string.

Now, you might be able to make more headway by offloading some of this logic on the compiler. You could change your method parameter from Func<T, object> to Func<T, TReturn> and use typeof(TReturn) within the method to determine what the compiler decided the return type of the expression was.

Of course, in the case of my example, you'll still be working against object. But, your example of x => x.IntegerProperty.ToString() will yield string, which is what you're looking for.

like image 151
Adam Maras Avatar answered Oct 02 '22 21:10

Adam Maras


Something like this might do the trick. It probably doesn't cover every possibility, but it's a start.

public static Type GetObjectType<T>(Expression<Func<T, object>> expr)
{
    if ((expr.Body.NodeType == ExpressionType.Convert) ||
        (expr.Body.NodeType == ExpressionType.ConvertChecked))
    {
        var unary = expr.Body as UnaryExpression;
        if (unary != null)
            return unary.Operand.Type;
    }
    return expr.Body.Type;
}
like image 42
LukeH Avatar answered Oct 02 '22 23:10

LukeH