Wichtige Die Frage ist nicht: „Was tut Queryable.OfType tun, es ist‚ wie der Code ich es erreichen, dass siehe‘Wie funktioniert Queryable.OfType?
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 diese gerade haben.
- Verwenden Reflexion einen Verweis auf die aktuelle Methode (OfType) greifen
- Erstellen Sie eine neue Methode, die genau die gleiche ist, indem Sie MakeGenericMethod verwenden, um den Typparameter der aktuellen Methode in genau die gleiche Sache zu ändern.
- Das Argument für diese neue Methode wird nicht Quelle sondern source.Expression sein. Das ist kein IQueryable, aber wir werden das Ganze an Expression.Call übergeben, also ist das in Ordnung.
- Anruf Expression.Call, vorbei
null
alsMethode (seltsam?)Beispiel und das klonierte Verfahren als Argumente. - Übergeben Sie das Ergebnis an CreateQuery und geben Sie das Ergebnis aus, das wie der sinnvollste Teil des Ganzen aussieht.
Nun ist die Wirkung dieses Verfahrens ist ein Ausdruck zurückzukehren, die der Betreiber teilt alle Werte wegzulassen zurückkehrt, wo der Typ nicht gleich TResult oder einer seiner Subtypen ist. Aber ich kann nicht sehen, wie die obigen Schritte das tatsächlich erreichen. Es scheint, einen Ausdruck zu erstellen, der eine Methode darstellt, die IQueryable <TResult> zurückgibt und den Rumpf dieser Methode einfach den gesamten Quellausdruck macht, ohne jemals den Typ zu betrachten. Ist es einfach zu erwarten, dass ein IQueryable-Provider einfach keine Datensätze zurückgibt, die nicht vom ausgewählten Typ sind?
Sind also die obigen Schritte in irgendeiner Weise falsch, oder sehe ich nur nicht, wie sie das Verhalten zur Laufzeit ergeben?
OK, habe ich das gerade? 1. Der Aufruf von MakeGenericMethod ist erforderlich, da Sie eine geöffnete OfType-Version mit einem Argument von YourType (separat) übergeben können, aber OfType nicht als ein Argument übergeben können. Dieser Teil macht zumindest Sinn. 2. Der Sinn von all dem ist, dem Provider einfach "go import OfType" zu sagen, anstatt einen Ausdruck einer Implementierung von OfType zu erzeugen. Fortsetzung im nächsten Kommentar ... –
Es kann jedoch nicht einfach etwas in der Art von Expression.OfType zurückgegeben werden (was ich aufgrund Ihrer Erklärung erwarten würde), weil das nicht wirklich existiert. Liefern sie stattdessen etwas, was dasselbe ist, wird nur aus irgendeinem Grund anders umgesetzt? –
Nein, es gibt etwas zurück, das einen Aufruf von 'Queryable.OfType' darstellt, genau wie' Select' ein 'IQueryable' zurückgibt, das die vorherige Abfrage mit einem angeketteten Aufruf von 'Queryable.Select' repräsentiert. Es ist kein * Ausdruck * von 'OfType', es ist ein Ausdruck, der einen * Aufruf * zu' OfType' darstellt. –