Frage

Wichtig Die Frage ist nicht „Was ist Queryable.OfType Sie , ist es "wie funktioniert der Code, den ich da sehe, dass erreichen?"

Nachdenken über Queryable.OfType sehe ich (nach einiger Bereinigung):

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

Lassen Sie mich sehen, ob ich habe diese gerade:

  1. Verwenden Reflexion einen Verweis auf die aktuelle Methode (OfType) zu greifen.
  2. Erstellen Sie eine neue Methode, die genau das gleiche, von Makegenericmethod mit dem Typ-Parameter der aktuellen Methode zu ändern, äh, genau das gleiche.
  3. Das Argument für diese neue Methode nicht Quelle, sondern source.Expression sein. Welches ist kein IQueryable, aber wir werden die ganze Sache zu Expression.Call werden vorbei, so dass in Ordnung ist.
  4. Rufen Sie Expression.Call, vorbei null als Methode (seltsam?) Beispiel: und die geklonte Methode als Argumente.
  5. Führen Sie dieses Ergebnis zu Create und wirft das Ergebnis, die wie der vernünftigste Teil des Ganzen zu sein scheint.

Nun ist die Wirkung dieser Methode ist, um einen Ausdruck zurück, die den Provider sagt alle Werte weglassen zurückkehrt, wo der Typ nicht gleich TResult oder einer seiner Subtypen ist. Aber ich kann nicht sehen, wie die oben genannten Schritte dies tatsächlich zu erreichen. Es scheint, einen Ausdruck zu erschaffen, ein Verfahren darstellt, die zurückgibt IQueryable , und machen den Körper dieser Methode einfach die gesamte Quellenausdruck, ohne jemals auf die Art zu suchen. Ist es einfach erwartet, dass ein IQueryable-Anbieter wird nur still keine Datensätze zurück nicht von der gewählten Art?

sind also die oben genannten Schritte nicht korrekt in irgendeiner Weise, oder bin ich einfach nicht sehen, wie sie in dem Verhalten führen zur Laufzeit beobachtet?

War es hilfreich?

Lösung

Es ist nicht vorbei in null als Methode - es ist vorbei es in als „Ziel Ausdruck“, das heißt, was es auf die Methode aufrufen. Dies ist null, weil OfType eine statische Methode ist, so dass es kein Ziel benötigen.

Der Punkt der Aufruf MakeGenericMethod ist, dass GetCurrentMethod() die offene Version zurückgibt, das heißt OfType<> statt OfType<YourType>.

Queryable.OfType selbst ist nicht bedeutet eine der Logik enthalten zum Weglassen alle Werte zurück. Das ist bis zu dem LINQ-Anbieter. Der Punkt der Queryable.OfType ist den Ausdrucksbaum aufzubauen, um den Anruf zu OfType zu umfassen, so dass, wenn der LINQ-Anbieter schließlich sie in ihrem nativen Format konvertieren hat (zum Beispiel SQL), dass OfType weiß genannt wurde.

Dies ist, wie Queryable im Allgemeinen funktioniert - im Grunde lässt es sich der Anbieter die gesamte Abfrage-Ausdruck als Ausdruck Baum zu sehen. Das ist alles, es zu tun, gemeint -., Wenn der Anbieter aufgefordert wird, dies in echten Code zu übersetzen, das ist , wo die Magie geschieht

Queryable kann unmöglich die Arbeit selbst - sie hat keine Ahnung, welche Art von Datenspeicher des Anbieter darstellt. Wie könnte es auch mit der Semantik von OfType kommen, ohne zu wissen, ob der Datenspeicher war SQL, LDAP oder etwas anderes? Ich bin damit einverstanden es eine Weile dauert, den Kopf Runde zu bekommen aber:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top