2016-04-03 8 views
0

Ich habe eine generische Liste. Ich muss die Liste basierend auf dem Wert der Eigenschaft des Listenelements filtern. Der Artikeltyp ist bis zur Laufzeit nicht bekannt.Wie kann ich generische Liste nach Reflexion in C#

Ich muss den Gegenstandstyp durch Reflexion finden und muss dann filtern.

Bitte helfen Sie mir von einer Idee oder ein Beispiel

Dank.

+0

Könnten Sie ein Codebeispiel von hinzufügen, was du bist versuchen zu tun/was du probiert hast? –

+0

Sie können '.OfType' auf Ihrer Liste verwenden, um nach Typ zu filtern:' list.OfType () '- aber es ist unwahrscheinlich, dass Ihre Anforderung" durch Reflektion "abgedeckt wird. –

+0

"Elementtyp ist bis zur Laufzeit nicht bekannt" - welchen Mechanismus verwenden Sie, um * den Elementtyp zur Laufzeit anzugeben *? Woher weißt du, dass der Typ (zur Laufzeit) die gewünschte Eigenschaft hat? Was ist dein Basistyp, der gegen die 'generische Liste' definiert ist oder ist es nur 'var list = new [];' und du hast nicht die richtigen Begriffe verwendet. Wenn Sie Ihren bisherigen Code hinzufügen, können Sie diese Fragen beantworten. –

Antwort

1

Ich hoffe, diese Hilfe

Pass jede Liste, und einen Eigenschaftsnamen angeben, und eine Filtermethode

 private IList FilterList(IList list, string propName, Predicate<object> filterMethod) { 
     var result = new List<object>(); 
     foreach (var item in list) { 
      var value = item.GetType().GetProperty(propName).GetValue(item); 
      if (filterMethod(value)) { 
       result.Add(item); 
      } 
     } 
     return result; 

    } 

Beispiel:

var result = FilterList(list, "Age", age => (int)age >= 18); 

Sie können es entwickeln und mach es voll dynamisch

+0

Danke @ yousif.aljamri, Ihre Lösung funktioniert, wenn ich den Eigenschaftstyp im Voraus kenne. In meinem Beispiel, wenn ich Age nicht in int umgebe, funktioniert es nicht. Ich kenne den Eigenschaftstyp nicht im Voraus. Wie kann ich dann filtern? –

+0

@BulbulAhmed Wie detailliert ist Ihr Filter? und von wo es kommt? Wenn es einfacher Textfilter ist, ist es einfacher –

1

Wenn die Liste generisch ist, sollten Sie mindestens einen Basistyp zur Kompilierzeit wissen.

Wenn der Basistyp die Eigenschaft enthält, verwenden Sie sie einfach.

Wenn nur einige der Subtypen (idealerweise eine) die Eigenschaft enthalten, an der Sie interessiert sind, können Sie in der Liste eine cast eingeben und dann Ihre Eigenschaft verwenden.

list.Cast<Derived>().Select(i => i.Property == "val"); 

Wenn das nicht in Ordnung ist (sagen, dass die Art der Liste viele abgeleitete Typen hat, die die Eigenschaft und andere enthalten, die nicht), können Sie dynamisch mit einem try/catch-Block verwenden können.

list.Select(i => { 
        try 
        { 
         dynamic item = i; 
         return item.Prop == "value"; 
        } 
        catch(RuntimeBinderException) //this type doesn't contain the property 
        { 
         return false; 
        } 
       }); 
+0

Dank @Bond, Ich kann nur den abgeleiteten Typ durch Reflexion kennen. Wie kann ich es in eine Liste seines Typs umwandeln? –

0

Versuchen Sie es. Es kann feststellen, ob eine Liste eine Liste eines bestimmten Typs ist. Basierend darauf sollten Sie in der Lage sein, nach einem bestimmten Typ zu filtern.

public class TypeA 
{ } 
public class TypeB 
{ } 

public class GenericFilter 
{ 
    public bool IsOfType<T>(IEnumerable<dynamic> objectToInspect) 
    { 
     var genericType = objectToInspect.GetType().GenericTypeArguments[0]; 
     return genericType == typeof(T); 
    } 
} 


[TestClass] 
public class UnitTest1 
{ 
    [TestMethod] 
    public void IdentifiesExpectedType() 
    { 
     var classToInspect = new List<TypeA>(); 
     var filter = new GenericFilter(); 
     Assert.IsTrue(filter.IsOfType<TypeA>(classToInspect)); 
    } 

    [TestMethod] 
    public void RejectsNonMatchingType() 
    { 
     var classToInspect = new List<TypeA>(); 
     var filter = new GenericFilter(); 
     Assert.IsFalse(filter.IsOfType<TypeB>(classToInspect)); 
    } 
} 

Dies funktioniert genauso gut:

public bool IsOfType<T>(IEnumerable<dynamic> listToFilter) 
{ 
    return (listToFilter as IEnumerable<T>) != null; 
} 

Dies wird eine Liste von Listen nehmen und gruppieren sie in eine Dictionary<Type, List<List<dynamic>> wo alle Listen für jeden Schlüssel davon sind Art. Auf diese Weise können Sie Listen vom Typ T auswählen, indem Sie sie einfach aus dem Wörterbuch abrufen.

public Dictionary<Type, List<List<dynamic>>> GroupListsByType(List<List<dynamic>> lists) 
    { 
     var types = lists.Select(list => list.GetType().GenericTypeArguments[0]).Distinct().ToList(); 
     var grouped = new Dictionary<Type, List<List<dynamic>>>(); 
     types.ForEach(type => 
     { 
      grouped.Add(type, new List<List<dynamic>>()); 
      grouped[type].AddRange(lists.Where(list=>list.GetType().GenericTypeArguments[0] == type)); 
     }); 
     return grouped; 
    } 

(ich bin nicht in Frage nach dem „Warum“. Ich weiß nicht, ob ich das empfehlen würde, aber es ist interessant zu schreiben.)