Wie funktioniert Queryable.OfType funktionieren?
-
10-07-2019 - |
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:
- Verwenden Reflexion einen Verweis auf die aktuelle Methode (OfType) zu greifen.
- Erstellen Sie eine neue Methode, die genau das gleiche, von Makegenericmethod mit dem Typ-Parameter der aktuellen Methode zu ändern, äh, genau das gleiche.
- 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.
- Rufen Sie Expression.Call, vorbei
null
alsMethode (seltsam?)Beispiel: und die geklonte Methode als Argumente. - 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
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?
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:)