我有一个接受Expression<Func<T, object>>
实例的方法。我希望得到特定表达式实例返回的实际数据类型,而不是object
。
我可以让它用于直接属性引用,所以如果我传入表达式x => x.IntegerProperty
,我可以得到一个整数的Type引用。这种方法需要将其转换为MemberExpression。
但是,我不能让它适用于任意表达式。例如,如果表达式为x => x.IntegerProperty.ToString()
,我想获得字符串的Type引用。我无法将其编译为MemberExpression,如果我只是.Compile()
并检查返回类型,我会得到“对象”。
如何查看特定的表达式实例并派生实际的返回类型?
答案 0 :(得分:22)
这样的事情可能会成功。它可能并未涵盖所有可能性,但它是一个开始。
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;
}
答案 1 :(得分:2)
虽然并非不可能,但这一点特别困难。它需要遍历表达式树并执行一些可能复杂的逻辑。例如,如果我传入以下表达式,您希望看到什么?
Func<bool, object> expr = switch => switch ? 1 : "False";
此方法可以返回int
或string
。
现在,您可以通过在编译器上卸载一些逻辑来取得更多进展。您可以将方法参数从Func<T, object>
更改为Func<T, TReturn>
,并在方法中使用typeof(TReturn)
来确定编译器决定表达式返回类型的内容。
当然,就我的例子而言,你仍然会反对object
。但是,x => x.IntegerProperty.ToString()
的示例会产生string
,这正是您所寻找的。 p>
答案 2 :(得分:0)
一种厚颜无耻的方式(它涉及实际调用Func
),但你可以这样做:
using System;
class Program
{
static Func<T,object> MakeFunc<T>()
{
return x => 23;
}
static Type GetReturnType<T>(Func<T,object> f)
{
return f(default(T)).GetType();
}
static void Main(string[] args)
{
Type t = GetReturnType(MakeFunc<string>());
Console.WriteLine(t);
}
}
不保证在所有情况下均可使用,我应该添加 - 特别是如果default(T)
不是Func
的有效参数。但这至少是一个潜在的起点。