2010-09-08 11 views
21

Ich brauche etwas zu können, ähnlich wie die Arbeit folgendes erhalten:IQueryable OfType <T> wobei T eine Laufzeit Typ

Type type = ??? // something decided at runtime with .GetType or typeof; 
object[] entityList = context.Resources.OfType<type>().ToList(); 

Ist das möglich? Ich bin in der Lage, .NET 4 zu verwenden, wenn etwas Neues darin erlaubt.

+3

Sie wollen, sich fragen: Warum? 'Vorsichtig. – leppie

+0

Muss es IQueryable sein? In Ihrem Beispiel scheint IEnumerable ausreichend zu sein. –

+0

@leppie Ich verstehe Ihren Punkt nicht .. – Tablet

Antwort

36

Sie können es durch Reflexion nennen:

MethodInfo method = typeof(Queryable).GetMethod("OfType"); 
MethodInfo generic = method.MakeGenericMethod(new Type[]{ type }); 
// Use .NET 4 covariance 
var result = (IEnumerable<object>) generic.Invoke 
     (null, new object[] { context.Resources }); 
object[] array = result.ToArray(); 

Eine Alternative wäre eine eigene OfTypeAndToArray generische Methode schreiben beide Bits, es zu tun, aber die oben funktionieren sollte.

+0

Skeet das funktioniert, was für eine Legende - ich werde nur SQL-Profiler verwenden, um zu sehen, ob es die Filterung nach dem Abrufen der Sammlung oder als Teil der Abfrage .. wenn nicht Sie kennen die Antwort auch! – Tablet

+1

@Shahin: Es sollte das Richtige tun - es heißt schließlich 'Queryable.Where' statt' Enumerable.Where'. –

+0

@Skeet hast du eine Idee, warum es von dem ersten Ergebnis, das es empfangen hat, im Cache gespeichert werden kann? – Tablet

-1
object[] entityList = context.Resources 
           .Where(t=> t.GetType() == type) 
           .ToArray(); 
+0

Wird das nicht den gesamten Inhalt der Ressourcen vor dem Ausführen der WHERE dagegen zurückgeben? Die Verwendung von OfType in diesem Kontext führt es in der SQL aus (ich verwende Zentity) – Tablet

+0

Zusätzlich zu dem, was Shahin sagte, ist dies auch falsch für polymorphe Typen. – Timwi

+0

Es sagt Namespace Name erwartet, wenn ich versuche und das tun – Tablet

8

Sieht aus wie Sie Reflection hier verwenden müssen werden ...

public static IEnumerable<object> DyamicOfType<T>(
     this IQueryable<T> input, Type type) 
{ 
    var ofType = typeof(Queryable).GetMethod("OfType", 
        BindingFlags.Static | BindingFlags.Public); 
    var ofTypeT = ofType.MakeGenericMethod(type); 
    return (IEnumerable<object>) ofTypeT.Invoke(null, new object[] { input }); 
} 

Type type = // ...; 
var entityList = context.Resources.DynamicOfType(type).ToList(); 
+0

Danke für Ihre Hilfe! – Tablet

0

rein auf Ihre Frage zu use "Generics", Nein, es ist nicht möglich.

Generics ist eine Kompilierzeitfunktion und keine Runtime-Erkennung. Zur Laufzeit müssen Sie Reflection oder Dynamic verwenden.

+2

Meh, ich mag nicht die Charakterisierung von "Generika ist eine Kompilierzeit Feature." Es ist dies und auch nachweislich ein Laufzeit-Feature (anders als Java). –

+0

Sie mögen es vielleicht nicht, aber wichtig ist, dass Generika eine Kompilierzeitfunktion ist. Generischer Typ wird mit dem Wissen des T. zusammengestellt. Wenn du es anders zeigen kannst, bitte erleuchte mich. – Aliostad

+0

Wenn es keine Laufzeitfunktion wäre, wie könnte MakeGenericType funktionieren? – Casey

0

was ist mit ...

public static IList OfTypeToList(this IEnumerable source, Type type) 
    { 
     if (type == null) 
      throw new ArgumentNullException(nameof(type)); 
     return 
      (IList) Activator.CreateInstance(
       typeof(List<>) 
        .MakeGenericType(type), 
       typeof(System.Linq.Enumerable) 
        .GetMethod(nameof(System.Linq.Enumerable.OfType), 
           BindingFlags.Static | BindingFlags.Public) 
        .MakeGenericMethod(type) 
        .Invoke(null, new object[] { source })); 
    } 
Verwandte Themen