C# 获得;“对象”;Func的返回类型<;MyClass,对象>;
假设我对Func的定义如下:C# 获得;“对象”;Func的返回类型<;MyClass,对象>;,c#,reflection,lambda,expression,C#,Reflection,Lambda,Expression,假设我对Func的定义如下: Func<MyClass, object> f = o => o.StringProperty; Func f=o=>o.StringProperty; 或 Func f=o=>o.Property.SomeMethod(); 有没有办法在不特别调用返回类型的情况下获取实际的返回类型?您可以通过使用泛型方法使编译器推断类型参数来实现这一点: static Func<T1, R> Infer<T1, R>(Func<
Func<MyClass, object> f = o => o.StringProperty;
Func f=o=>o.StringProperty;
或
Func f=o=>o.Property.SomeMethod();
有没有办法在不特别调用返回类型的情况下获取实际的返回类型?您可以通过使用泛型方法使编译器推断类型参数来实现这一点:
static Func<T1, R> Infer<T1, R>(Func<T1, R> f) { return f; }
这将在编译时将返回类型编码为func
类型
当然,对于更普遍适用的解决方案,您需要一组expert
重载来覆盖Action
和Func
,并使用一个、两个、三个等参数
如果您希望在运行时获取返回类型,对于任何类型的
Func
,都可以像ppetrov已经指出的Func.Method.ReturnType
一样简单。您可以获得如下返回类型:
f.Method.ReturnType
但这将返回类型对象
。如果要获取方法
或字符串
或从对象
派生的内容,除非调用该方法,否则将无法获取信息
实际上可以,但这意味着您必须分解方法核心,然后对其进行分析,以查看方法可以返回什么。但即便如此,也可能有许多不同的回报类型
所以答案是:如果您想知道它返回一个对象,那么可以,否则就不值得麻烦了,最好找到另一种方法来完成您需要的操作。因为您在运行时从其他源检索这些
Func
委托,类型信息基本上丢失了
相反,在定义这些函数的地方,您可以让调用者利用API在包装委托中对该类型信息进行编码(EDIT:Silly me,此时要简单得多;我们已经有了通用编译时信息):
您的API需要一个MyClassDelegate
,您可以使用它轻松访问它们的类型:
Console.WriteLine(f1.ReturnType.FullName); //string
Console.WriteLine(f2.ReturnType.FullName); //whatever `SomeMethod()` is declared to return
最后,您还可以调用委托,甚至创建Func
委托:
f1.Invoke(myClassInstance);
Func<MyClass, object> f3 = f1.Invoke;
f1.Invoke(myClassInstance);
Func f3=f1.Invoke;
“获取”返回类型的准确程度如何?一个假设的例子?@Jon我认为根据编译器知道的事实推断返回类型(在第一个例子中是string
,在第二个例子中是SomeMethod
的返回),但是这个例子会在运行时崩溃,因为变量f
可能被重新分配。假设,如果不能重新分配f
,您可以通过解析Func
定义静态确定返回类型。听起来像是Roslyn的候选人;-)根据您的使用情况,也许您可以利用表达式
API来检查返回类型:(这不是您试图执行的操作的精确实现,只是一个相关的示例)如果您有Func f1=o=>o.StringProperty;Func f2=o=>f1(o)代码>?甚至Func f=o=>{throw new NotImplementedException();}代码>?:)@这是一个关于投掷的好问题exception@EugeneD.Gubenkov:当然,如果您已经有了Func f=s=>s.Length
,并且您确实有expert(f)
,您将得到一个Func
——无法恢复已“丢失”的类型信息@EugeneD.Gubenkov:如果你想做得更多,那么你必须使用表达式和反射;此时不需要LINQ表达式API。关键是在创建委托时让调用方对这些信息进行编码,并利用包装好的委托在整个API中传递信息。谢谢您的详细回答。当我们想要正确地做这些事情时,我们无论如何都应该使用表达式,我明白了。Expression
用法只有在你想要避免泛型推理的情况下才有帮助。也就是说,您可以使用Create(Expression function)
并仍然确定使用的类型。但您也可以利用我在更新中使用的泛型类型推断。是的,我只是想找到没有泛型类型的非编译时解决方案。
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 f1 = MyClassDelegate.Create(o => o.StringProperty);
MyClassDelegate f2 = MyClassDelegate.Create(o => o.Property.SomeMethod());
Console.WriteLine(f1.ReturnType.FullName); //string
Console.WriteLine(f2.ReturnType.FullName); //whatever `SomeMethod()` is declared to return
f1.Invoke(myClassInstance);
Func<MyClass, object> f3 = f1.Invoke;