C# 生成对应于Enumerable.Cast的已编译委托<;T>;?

C# 生成对应于Enumerable.Cast的已编译委托<;T>;?,c#,reflection,expression-trees,C#,Reflection,Expression Trees,这是一个非常棘手的问题,我在调用泛型方法(MethodInfo)时遇到了麻烦,该方法是由表达式树上下文中的另一个MethodCallExpression(通过使用MakeGenericMethod)返回的 从技术上讲,我想要的编译委托如下所示: Func<IEnumerable, Type, IEnumerable> cast; 所以,正如你所看到的,这是一个非常棘手的问题,以前从未遇到过这样的问题。我知道我可以通过调用castMethod(作为MethodCallExpressi

这是一个非常棘手的问题,我在调用泛型方法(
MethodInfo
)时遇到了麻烦,该方法是由表达式树上下文中的另一个
MethodCallExpression
(通过使用
MakeGenericMethod
)返回的

从技术上讲,我想要的编译委托如下所示:

Func<IEnumerable, Type, IEnumerable> cast;

所以,正如你所看到的,这是一个非常棘手的问题,以前从未遇到过这样的问题。我知道我可以通过调用
castMethod
(作为
MethodCallExpression
)来解决这个问题。这样,我需要获得
MethodInfo
Invoke
方法,并使用
Expression.Call
在实例
castMethod
上调用该方法。但是等等,如果是这样的话,我们仍然使用
方法。调用
,就像我们使用
反射
来编写代码,而通常不编译它?我真的相信
表达式有一些隐藏的魔力。Call
MethodInfo做得不同(更好更快)。Invoke

你试图做的事情完全没有意义,而且与
Enumerable.Cast
非常不同,后者实际上做了一些有用的事情

让我们看看后者的定义:

IEnumerable<T> Cast<T>(this IEnumerable source);
IEnumerable Cast(this IEnumerable items, Type type);
这将获取一个非类型化的可枚举项,并返回一个非类型化的可枚举项。它在内部所做的并不重要,因为即使它按您想要的方式工作,您从中得到的仍然是可枚举的纯
对象
s,因此要使用这些值,您仍然需要正确地强制转换这些值(并取消装箱值类型的装箱)。你什么也没得到,你已经有了这样一个集合——你首先传递给你函数的东西


即使您使用编译表达式的缓存(每种类型一个)使强制转换工作,这并不困难,但输出仍然会通过返回类型强制转换回
对象。

您尝试执行的操作完全没有意义,并且与
Enumerable.cast非常不同,后者实际上做了一些有用的事情

让我们看看后者的定义:

IEnumerable<T> Cast<T>(this IEnumerable source);
IEnumerable Cast(this IEnumerable items, Type type);
这将获取一个非类型化的可枚举项,并返回一个非类型化的可枚举项。它在内部所做的并不重要,因为即使它按您想要的方式工作,您从中得到的仍然是可枚举的纯
对象
s,因此要使用这些值,您仍然需要正确地强制转换这些值(并取消装箱值类型的装箱)。你什么也没得到,你已经有了这样一个集合——你首先传递给你函数的东西


即使使用编译表达式的缓存(每种类型一个)使强制转换工作,这并不困难,但输出仍然会通过返回类型强制转换回
对象。

类型必须在编译表达式时知道。它不能是已编译委托的输入。如果您编写的方法接受
类型
并返回
Func
(即内部调用
.Cast()
,其中
T
是您传入的类型的委托),则可以执行该操作work@canton7如果是这样的话,对我来说太容易了,这样做并没有带来太多好处。我们事先有很多未知的
类型
(目标施法类型)。因此,我们需要为每种类型构建每个委托并将其全部缓存?如果无法做到这一点,我希望每次都直接使用反射,尽可能多地使用缓存,并基于
MethodInfo.Invoke
的速度,这并不是很糟糕,但当然也不比编译委托好。是的。当然,另一种选择是使用反射调用Cast。但是,我不确定你能得到多少好处?你只能真正做参考conversions@canton7我认为最昂贵的操作涉及
MethodInfo.Invoke
,因此我试图避免它。
Type
必须在编译表达式时知道。它不能是已编译委托的输入。如果您编写的方法接受
类型
并返回
Func
(即内部调用
.Cast()
,其中
T
是您传入的类型的委托),则可以执行该操作work@canton7如果是这样的话,对我来说太容易了,这样做并没有带来太多好处。我们事先有很多未知的
类型
(目标施法类型)。因此,我们需要为每种类型构建每个委托并将其全部缓存?如果无法做到这一点,我希望每次都直接使用反射,尽可能多地使用缓存,并基于
MethodInfo.Invoke
的速度,这并不是很糟糕,但当然也不比编译委托好。是的。当然,另一种选择是使用反射调用Cast。但是,我不确定你能得到多少好处?你只能真正做参考conversions@canton7我认为最昂贵的操作涉及
MethodInfo.Invoke
,因此我试图避免它。您对
IEnumerable强制转换(这个IEnumerable项,类型)
的假设是错误的,当然我们不会像往常一样在代码中明确使用它,我们在
反射
的上下文中使用它,输入的
和返回的
IEnumerable
的值完全不同(例如,您可以调用
GetType
来了解差异)。
items
类型无法在其他方法中传递,因此我们需要在此处执行
Cast
。所有操作都是使用反射(和
表达式
)完成的,没有强类型。是什么让您认为强制转换引用类型会改变其
GetType
类型?这是一个虚拟函数,转换引用类型不会更改其虚拟接口。我们不会转换整个项,而是对每个项进行转换。因此,不是将
IEnumerable
作为输入,而是将
IEnumerable
作为输出。这只是一个简单的例子。相信我,我做了大量的反射,没有这样的
转换
,代码只会在运行时出错。使用
Cast
,它可以工作。那你觉得呢