从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";
此方法可以返回int
或string
。
现在,您可以通过在编译器上卸载一些逻辑来取得更大的进展。 您可以将方法参数从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
的有效参数。 但这至少是一个潜在的起点。