Queryable.OfType如何工作? [英] How Does Queryable.OfType Work?

查看:53
本文介绍了Queryable.OfType如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

重要问题不是"Queryable.OfType 做什么做什么,而是我在那看到的代码是如何做到这一点的?"

Important The question is not "What does Queryable.OfType do, it's "how does the code I see there accomplish that?"

在Queryable.OfType上,我看到了(经过一些清理):

Reflecting on Queryable.OfType, I see (after some cleanup):

    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 }));
    }

所以,让我看看我是否已经明白了:

So let me see if I've got this straight:

  1. 使用反射获取对当前方法(OfType)的引用.
  2. 通过使用MakeGenericMethod将当前方法的类型参数更改为完全相同的方法,来创建一个完全相同的新方法.
  3. 该新方法的参数不是source,而是source.Expression.这不是一个IQueryable,但是我们会将整个内容传递给Expression.Call,这样就可以了.
  4. 调用Expression.Call,将null作为方法(很奇怪?)作为实例传递,并将克隆的方法作为参数传递.
  5. 将结果传递给CreateQuery并强制转换结果,这似乎是整个过程中最精妙的部分.
  1. Use reflection to grab a reference to the current method (OfType).
  2. Make a new method, which is exactly the same, by using MakeGenericMethod to change the type parameter of the current method to, er, exactly the same thing.
  3. The argument to that new method will be not source but source.Expression. Which isn't an IQueryable, but we'll be passing the whole thing to Expression.Call, so that's OK.
  4. Call Expression.Call, passing null as method (weird?) instance and the cloned method as its arguments.
  5. Pass that result to CreateQuery and cast the result, which seems like the sanest part of the whole thing.

现在,此方法的效果是返回一个表达式,该表达式告诉提供程序在类型不等于TResult或其子类型之一的情况下忽略返回任何值.但是我看不到上面的步骤实际上是如何实现的.似乎正在创建一个表达式,该表达式表示返回IQueryable< TResult>的方法,并使该方法的主体只是整个源表达式,而无需查看类型.是否只是期望IQueryable提供程序会静默不返回任何非选定类型的记录?

Now the effect of this method is to return an expression which tells the provider to omit returning any values where the type is not equal to TResult or one of its subtypes. But I can't see how the steps above actually accomplish this. It seems to be creating an expression representing a method which returns IQueryable<TResult>, and making the body of that method simply the entire source expression, without ever looking at the type. Is it simply expected that an IQueryable provider will just silently not return any records not of the selected type?

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

So are the steps above incorrect in some way, or am I just not seeing how they result in the behavior observed at runtime?

推荐答案

它没有将null作为方法传递-而是将其作为目标表达式"传递,即调用该方法的内容.这是空的,因为OfType是静态方法,因此不需要目标.

It's not passing in null as the method - it's passing it in as the "target expression", i.e. what it's calling the method on. This is null because OfType is a static method, so it doesn't need a target.

调用MakeGenericMethod的要点是GetCurrentMethod()返回打开的版本,即OfType<>而不是OfType<YourType>.

The point of calling MakeGenericMethod is that GetCurrentMethod() returns the open version, i.e. OfType<> instead of OfType<YourType>.

Queryable.OfType本身不是 meant 包含任何省略返回任何值的逻辑.这取决于LINQ提供程序. Queryable.OfType的重点是构建表达式树以包含对OfType的调用,因此,当LINQ提供程序最终不得不将其转换为其原始格式(例如SQL)时,它知道已调用OfType.

Queryable.OfType itself isn't meant to contain any of the logic for omitting returning any values. That's up to the LINQ provider. The point of Queryable.OfType is to build up the expression tree to include the call to OfType, so that when the LINQ provider eventually has to convert it into its native format (e.g. SQL) it knows that OfType was called.

这通常是Queryable的工作方式-基本上,它使提供程序将整个查询表达式视为一个表达式树.这就是所有要做的事情-当要求提供者将其转换为真实代码时,那是发生魔法的地方.

This is how Queryable works in general - basically it lets the provider see the whole query expression as an expression tree. That's all it's meant to do - when the provider is asked to translate this into real code, that's where the magic happens.

Queryable本身无法完成工作-它不知道提供程序代表什么样的数据存储.在不知道数据存储是SQL,LDAP还是其他东西的情况下,如何提出OfType的语义?我同意,花点时间来解决这个问题:)

Queryable couldn't possibly do the work itself - it has no idea what sort of data store the provider represents. How could it come up with the semantics of OfType without knowing whether the data store was SQL, LDAP or something else? I agree it takes a while to get your head round though :)

这篇关于Queryable.OfType如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆