假设我已按如下方式定义Func:
Func<MyClass, object> f = o => o.StringProperty;
或
Func<MyClass, object> f = o => o.Property.SomeMethod();
有没有办法获得实际返回类型而不专门调用它?
答案 0 :(得分:5)
你可以得到这样的返回类型:
f.Method.ReturnType
但是这会返回object
类型。如果您想获得Method
或String
或来自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
的重载来覆盖Action
和Func
以及一个,两个,三个等参数。
如果你想在运行时获得返回类型,对于任何类型的Func
,就像ppetrov已经指出的那样简单func.Method.ReturnType
。