从Func <myclass,object =“”> </myclass,>获取“对象”返回类型

时间:2013-07-24 14:29:27

标签: c# reflection lambda expression

假设我已按如下方式定义Func:

Func<MyClass, object> f = o => o.StringProperty;

Func<MyClass, object> f = o => o.Property.SomeMethod();

有没有办法获得实际返回类型而不专门调用它?

3 个答案:

答案 0 :(得分:5)

你可以得到这样的返回类型:

f.Method.ReturnType

但是这会返回object类型。如果您想获得MethodString或来自object的内容,除非您致电该方法,否则您将无法获得相关信息。

实际上你可以,但这意味着你必须对方法核心进行反汇编,然后对其进行分析以查看该方法可以返回的内容。但即便如此,也许会有很多不同的回报类型。

所以答案是:如果你想知道它返回一个对象,那么你可以,否则它不值得麻烦,而且找到另一种方法来做你的事情会更好需要。

答案 1 :(得分:2)

由于您是在运行时从其他来源检索这些Func<MyClass, object>委托,因此类型信息基本上会丢失。

相反,在定义这些函数的地方,您可以让调用者通过利用LINQ Expression API 在包装的委托中实际编码该类型信息(编辑:傻我,远此时更简单;我们已经有了通用编译时信息):

public class MyClassDelegate
{
    private readonly Func<MyClass, object> Function;

    public Type ReturnType { get; private set; }

    private MyClassDelegate(Func<MyClass, object> function, Type returnType)
    {
        this.Function = function;
        this.ReturnType = returnType;
    }

    public object Invoke(MyClass context)
    {
        return Function(context);
    }

    public static MyClassDelegate Create<TReturnType>(Func<MyClass, TReturnType> function)
    {
        Func<MyClass, object> nonTypedFunction = o => function(o);
        return new MyClassDelegate(nonTypedFunction, typeof(TReturnType));
    }
}

(也可以使用派生的通用MyClassDelegate<TReturnType> : MyClassDelegate类来解决Create方法中的一些愚蠢问题,或者避免使用值类型装箱,或者获取返回类型信息编译时间甚至反映MyClassDelegate<TReturnType>的任何内容。)

定义代理而不是直接使用Func<MyClass, object>的调用者将改为使用此类并将其委托定义为:

MyClassDelegate f1 = MyClassDelegate.Create(o => o.StringProperty);
MyClassDelegate f2 = MyClassDelegate.Create(o => o.Property.SomeMethod());

您的API需要MyClassDelegate,您可以使用该Console.WriteLine(f1.ReturnType.FullName); //string Console.WriteLine(f2.ReturnType.FullName); //whatever `SomeMethod()` is declared to return 轻松访问其类型:

Func<MyClass, object>

最后,您可以调用代理,甚至可以创建f1.Invoke(myClassInstance); Func<MyClass, object> f3 = f1.Invoke; 代理:

{{1}}

答案 2 :(得分:1)

通过使用泛型方法使编译器推断出类型参数,可以做一些与此相近的事情:

static Func<T1, R> Infer<T1, R>(Func<T1, R> f) { return f; }

然后:

var func = Infer((string s) => s.Length);

这将在编译时将返回类型编码为func类型。

当然,对于更普遍适用的解决方案,您需要一堆Infer的重载来覆盖ActionFunc以及一个,两个,三个等参数。

如果你想在运行时获得返回类型,对于任何类型的Func,就像ppetrov已经指出的那样简单func.Method.ReturnType