重要的问题不是“Queryable.OfType 是什么?do,它是“我在那里看到的代码如何实现这一点?”
反思 Queryable.OfType,我看到(经过一些清理后):
public static IQueryable<TResult> OfType<TResult>(this IQueryable source)
{
return (IQueryable<TResult>)source.Provider.CreateQuery(
Expression.Call(
null,
((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(
new Type[] { typeof(TResult) }) ,
new Expression[] { source.Expression }));
}
那么让我看看我是否明白了这一点:
- 使用反射来获取对当前方法 (OfType) 的引用。
- 通过使用 MakeGenericMethod 将当前方法的类型参数更改为,呃,完全相同的东西,创建一个完全相同的新方法。
- 该新方法的参数不是 source,而是 source.Expression。这不是 IQueryable,但我们将把整个事情传递给 Expression.Call,所以没关系。
- Call Expression.Call, passing
null
as method (weird?) instance and the cloned method as its arguments.
- 将该结果传递给 CreateQuery 并转换结果,这似乎是整个事情中最明智的部分。
现在,此方法的效果是返回一个表达式,该表达式告诉提供程序忽略返回类型不等于 TResult 或其子类型之一的任何值。但我看不出上面的步骤实际上是如何实现这一点的。它似乎正在创建一个表示返回 IQueryable 的方法的表达式,并使该方法的主体只是整个源表达式,而无需查看类型。是否只是期望 IQueryable 提供程序会默默地不返回任何不属于所选类型的记录?
那么,上述步骤在某种程度上是否不正确,或者我只是没有看到它们如何导致运行时观察到的行为?
它没有传入null
作为方法 - 它将它作为“目标表达式”传递,即它调用该方法的内容。这是空的,因为OfType
是静态方法,因此不需要目标。
打电话的要点MakeGenericMethod
就是它GetCurrentMethod()
返回开放版本,即OfType<>
代替OfType<YourType>
.
Queryable.OfType
本身不是meant包含省略返回任何值的任何逻辑。这取决于 LINQ 提供商。要点是Queryable.OfType
是构建表达式树以包含对OfType
,这样当 LINQ 提供程序最终必须将其转换为其本机格式(例如 SQL)时,它就知道OfType
被称为。
就是这样Queryable
一般来说,它可以让提供者将整个查询表达式视为表达式树。这就是它的全部目的 - 当要求提供者将其转换为真实代码时,that's奇迹发生的地方。
Queryable
它本身不可能完成这项工作 - 它不知道提供者代表什么类型的数据存储。它怎么能得出这样的语义OfType
不知道数据存储是 SQL、LDAP 还是其他?我同意你需要一段时间才能清醒过来:)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)