简体   繁体   English

从表达式中获取实际返回类型<Func<T, object> &gt; 实例

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

I have a method that accepts a Expression<Func<T, object>> instance.我有一个接受Expression<Func<T, object>>实例的方法。 I want to get at the actual data type being returned by a specific expression instance, rather than object .我想获取特定表达式实例返回的实际数据类型,而不是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.我可以让它用于直接属性引用,所以如果我传入表达式x => x.IntegerProperty我可以获得一个整数的 Type 引用。 This approach requires converting it to a MemberExpression.这种方法需要将其转换为 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.例如,如果表达式是x => x.IntegerProperty.ToString()我想获得一个字符串的类型引用。 I can't compile this to a MemberExpression, and if I just .Compile() it and check the return type I get "object".我无法将其编译为 MemberExpression,如果我只是.Compile()它并检查返回类型,我会得到“对象”。

How can I look at the specific expression instance and derive the actual return type?如何查看特定的表达式实例并得出实际的返回类型?

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;
}

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 .此方法可以返回intstring

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.您可以将方法参数从Func<T, object>更改为Func<T, TReturn>并在方法中使用typeof(TReturn)来确定编译器决定表达式的返回类型是什么。

Of course, in the case of my example, you'll still be working against object .当然,在我的例子中,你仍然会使用object But, your example of x => x.IntegerProperty.ToString() will yield string , which is what you're looking for.但是,您的x => x.IntegerProperty.ToString()示例将产生string ,这就是您要查找的内容。

Bit of a cheeky way (and it involves actually invoking the Func ), but you can do this:有点厚颜无耻的方式(它涉及实际调用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);
    }
}

It's not guaranteed to work in all situations, I should add - particularly if the default(T) isn't a valid parameter to the Func .不能保证在所有情况下都能工作,我应该补充 - 特别是如果default(T)不是Func的有效参数。 But it's a potential starting point at least.但这至少是一个潜在的起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM