代码之家  ›  专栏  ›  技术社区  ›  Craig Stuntz

queryable.oftype如何工作?

  •  5
  • Craig Stuntz  · 技术社区  · 15 年前

    重要的 问题不是“queryable.oftype是什么?” ,它是“我看到的代码是如何完成的?”

    考虑到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 }));
        }
    

    所以让我看看我有没有直截了当地说:

    1. 使用反射获取对当前方法(OfType)的引用。
    2. 通过使用MakeGenericMethod将当前方法的类型参数更改为,er,完全相同,从而生成一个完全相同的新方法。
    3. 新方法的参数将不是source,而是source.expression。这不是iqueueryable,但我们将把整个过程传递给表达式。调用,这样就可以了。
    4. 调用表达式。调用,传递 null 作为 方法(怪异?) 实例 以及克隆的方法作为其参数。
    5. 将该结果传递给createQuery并强制转换该结果,这似乎是整个过程中最理智的部分。

    现在,此方法的效果是返回一个表达式,该表达式指示提供程序忽略返回类型不等于tresult或其子类型之一的任何值。但我看不出上面的步骤是如何实现这一点的。它似乎正在创建一个表达式,该表达式表示一个返回iQuery<tresult>的方法,并使该方法的主体成为整个源表达式,而不必查看该类型。是否只是期望IQueryable提供程序只静默地不返回任何非所选类型的记录?

    那么,上面的步骤是否在某种程度上不正确,或者我只是没有看到它们如何导致在运行时观察到的行为?

    1 回复  |  直到 15 年前
        1
  •  5
  •   Jon Skeet    15 年前

    它不会进来的 null 作为方法-它将其作为“目标表达式”传入,即它调用方法的对象。这是空的,因为 OfType 是静态方法,因此不需要目标。

    呼叫点 MakeGenericMethod 那是 GetCurrentMethod() 返回打开的版本,即 OfType<> 而不是 OfType<YourType> .

    Queryable.OfType 本身不是 意味 包含省略返回任何值的逻辑。这取决于LINQ提供商。要点 可查询.oftype 是建立表达式树以包含对 OfType ,以便当LINQ提供程序最终必须将其转换为其本机格式(例如SQL)时,它知道 OfType 被叫来。

    就是这样 Queryable 一般来说可以工作——基本上,它让提供者将整个查询表达式看作一个表达式树。这就是它所要做的-当提供者被要求将它转换成真正的代码时, 那是 魔法发生的地方。

    可查询的 无法自己完成工作-它不知道提供程序代表的是哪种数据存储。它怎么能得出 OfType 不知道数据存储是SQL、LDAP还是其他什么?我同意你需要一段时间才能清醒过来。)