从Expression <Func >实例获取实际返回类型

我有一个接受Expression<Func>实例的方法。 我想得到特定表达式实例返回的实际数据类型,而不是object

我可以让它用于直接属性引用,所以如果我传入表达式x => x.IntegerProperty我可以得到一个整数的Type引用。 此方法需要将其转换为MemberExpression。

但是,我不能让它为任意表达式工作。 例如,如果表达式是x => x.IntegerProperty.ToString()我想获得字符串的Type引用。 我无法将其编译为MemberExpression,如果我只是.Compile()它并检查返回类型我得到“对象”。

如何查看特定的表达式实例并派生实际的返回类型?

像这样的东西可能会成功。 它可能并未涵盖所有可能性,但它是一个开始。

 public static Type GetObjectType(Expression> 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; } 

虽然并非不可能,但这尤其困难。 它需要遍历表达式树并执行一些可能复杂的逻辑。 例如,如果我传入以下表达式,您希望看到什么?

 Func expr = switch => switch ? 1 : "False"; 

此方法可以返回intstring

现在,您可以通过在编译器上卸载一些逻辑来取得更大的进展。 您可以将方法参数从Func更改为Func并在方法中使用typeof(TReturn)来确定编译器决定表达式的返回类型的内容。

当然,就我的例子而言,你仍然会反对object 。 但是,你的x => x.IntegerProperty.ToString()例子将产生string ,这是你正在寻找的。

一点厚颜无耻的方式(它涉及实际调用Func ),但你可以这样做:

 using System; class Program { static Func MakeFunc() { return x => 23; } static Type GetReturnType(Func f) { return f(default(T)).GetType(); } static void Main(string[] args) { Type t = GetReturnType(MakeFunc()); Console.WriteLine(t); } } 

它不能保证在所有情况下都能工作,我应该添加 – 特别是如果default(T)不是Func的有效参数。 但这至少是一个潜在的起点。