5

重要問題は、「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 を使用して、現在のメソッドの型パラメーターをまったく同じものに変更することにより、まったく同じ新しいメソッドを作成します。
  3. その新しいメソッドへの引数は、source ではなく source.Expression になります。これは IQueryable ではありませんが、すべてを Expression.Call に渡すので、問題ありません。
  4. Expression.Call を呼び出し、メソッド (変ですか?)インスタンスnullとして渡し、クローン化されたメソッドをその引数として渡します。
  5. その結果を CreateQuery に渡し、結果をキャストします。これは、全体の中で最も健全な部分のようです。

このメソッドの効果は、型が TResult またはそのサブタイプの 1 つと等しくない値を返すことを省略するようプロバイダーに指示する式を返すことです。しかし、上記の手順が実際にこれをどのように達成するかわかりません。IQueryable<TResult> を返すメソッドを表す式を作成し、そのメソッドの本体を単純にソース式全体にして、型を見ないようにしているようです。IQueryable プロバイダーが、選択されたタイプ以外のレコードを黙って返さないことが単純に期待されるのでしょうか?

上記の手順は何らかの点で間違っていますか、それとも実行時に観察される動作がどのように発生するかわかりませんか?

4

1 に答える 1

5

nullメソッドとして渡すのではなく、「ターゲット式」、つまりメソッドを呼び出す対象として渡します。これはOfType静的メソッドであるため null であり、ターゲットは必要ありません。

呼び出しのポイントは、開いているバージョンMakeGenericMethodGetCurrentMethod()返すことOfType<>です。つまり、 OfType<YourType>.

Queryable.OfTypeそれ自体には、値を返すことを省略するためのロジックを含めることは意図されていません。それは LINQ プロバイダー次第です。のポイントはQueryable.OfType、式ツリーを構築して への呼び出しを含めることOfTypeです。これにより、LINQ プロバイダーが最終的にそれをネイティブ形式 (SQL など) に変換する必要があるときに、それOfTypeが呼び出されたことを認識できます。

これがQueryable一般的な仕組みです。基本的に、プロバイダーはクエリ式全体を式ツリーとして見ることができます。本来の目的はそれだけです。プロバイダーがこれを実際のコードに変換するように求められると、魔法が起こります。

Queryableおそらく、それ自体で作業を行うことはできません。プロバイダーが表すデータ ストアの種類がわかりません。OfTypeデータ ストアが SQL なのか、LDAP なのか、それとも何か他のものなのかを知らずに、どうやってセマンティクスを思いつくことができるでしょうか? 私はあなたの頭を丸めるのに時間がかかることに同意します:)

于 2009-09-17T16:49:16.447 に答える