2016-05-10 4 views
-1
mit

Hier ist mein SzenarioWie filtern Liste <object> Linq/Lambda

List<object> obj = new List<object>(); 
obj.Add(new {id = 1, name = "Jakob"}); 
obj.Add(new {id = 2, name = "Sam"}); 
obj.Add(new {id = 3, name = "Albert"}); 
obj.Add(new {id = 1, name = "Jakob"}); 

Wie Sie List<object> wie diese Filter haben, so dass es eine Liste der Benutzer mit dem Namen „Jakob“ zurückkehrt?

obj.Where(t => t.name == "Jakob") funktioniert nicht

+0

Sie wären besser dran, ein Array zu initialisieren, damit es den anonymen Typ annimmt, wie 'var stuff = new [] {new {id = 1, name =" Jakob "}, ....}; Wenn Sie das Wo tun, wird der Lambda den Typ kennen und Sie können auf die Eigenschaften zugreifen. Entweder das oder Wechsel von "Objekt" zu "dynamisch". – juharr

Antwort

-1

könnten Sie Reflexion

var l = new List<object>(); 
    l.Add(new {key = "key1", v = "value1"}); 
    l.Add(new {key = "key2", v = "value2", v2="another value"}); 
    l.Add(new {key = "key3", v = "value3", v3= 4}); 
    l.Add(new {key = "key4", v = "value4", v4 = 5.3}); 

    var r = l.Where(x=> (string)x.GetType().GetProperty("key")?.GetValue(x) == "key1"); 

Holen Sie die Art Ihrer Elemente verwenden und die Eigenschaft, die Sie suchen, nicht finden. Holen Sie dann den Wert für die aktuelle Instanz und vergleichen Sie ihn mit dem Wert, nach dem Sie filtern möchten.

Auf der anderen Seite hat dieser Ansatz den Vorteil, auch dann zu arbeiten, wenn die Liste Elemente mehrerer anonymer Typen enthält (wenn sie unterschiedliche Eigenschaften haben), solange sie alle die Eigenschaft haben, nach der Sie filtern.

EDIT

Mit C# 6 können Sie den ? Operator verwenden, die Art eines Inline-Check für null ist. Dh, wenn GetProperty() kehrt null, da die Eigenschaft nicht gefunden wird, der Ausdruck null kehrt ohne GetValue() Ausführung

+0

Danke, dass deine Lösung für mich funktioniert hat. Ich denke, Reflexion war die einzige Lösung. Ich gehe normalerweise von der Reflexion weg, aber verzweifelte Zeit erfordert verzweifelte Maßnahmen. Ich war zu tief, dass ich keine anderen Methoden verwenden konnte. – wenn32

4

Wenn Sie Ihr Objekt dynamisch konvertieren, sollte es funktionieren:

obj.Where(t => ((dynamic)t).name == "Jakob") 

EDIT:

Der Vollständigkeit halber sollte ich einige Dinge erwähnen:

  • Verwendung des dynamischen Typs c Es geht um die Verwendung von Objekten mit Reflexion darüber, so dass Sie schließlich nicht etwas Besseres als Reflexion erhalten, wenn Sie diesen Ansatz verwenden.
  • Die Verwendung von dynamic beinhaltet das Laden notwendiger Assemblys (auch DLR genannt) in CLR, die nicht geladen würden, wenn Sie überhaupt nicht dynamisch arbeiten. Mit anderen Worten, es ist ein Overhead.

So, verwenden Sie mit Ihrer eigenen Diskretion.

+0

wie Ihre Idee, aber es wirft "'Objekt' enthält keine Definition für 'Name'" – wenn32

+0

Aber es funktionierte für mich ... sind Sie sicher, dass Sie den genauen Code, den Sie haben? Ich habe gerade in VS 2013 versucht, funktioniert gut. – Tengiz

+0

Ich versuchte "obj.Where (t => ((string) ((dynamische) t) .name). Enthält (" Jakob ")" – wenn32

4

Die beste Option, die Sie haben, besteht darin, eine Klasse zu deklarieren, die einen Benutzer darstellt.

public class User 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

dann eine Liste von User Objekte erstellen und diese Liste abfragen.

var users = new List<User> 
{ 
    new User { Id = 1, Name = "Jakob" }, 
    new User { Id = 2, Name = "Sam" }, 
    new User { Id = 3, Name = "Albert" } 
} 

var filteredUsers = users.Where(user => user.Name == "Jakob"); 

Andernfalls müssen Sie sich auf die von Tengiz vorgeschlagene Lösung verlassen.

0

Noch eine weitere Alternative Array von anonymen Typen erstellen (was sonst ein NullReferenceException werfen würde) und es dann über ToListIEnumerable zur Liste konvertieren Erweiterungsmethode:

var obj = (new[] { 
    new { id = 1, name = "Jakob" }, 
    new { id = 2, name = "Sam" }, 
    new { id = 3, name = "Albert" }, 
    new { id = 1, name = "Jakob" }}).ToList(); 
obj.Where(c => c.name == "Jakob"); 

Wenn Sie wirklich keine Liste benötigen und Array ist zu fein - nur nicht konvertieren aufzulisten.Vorteil ist, dass Sie eine stark typisierte Liste und keine Liste von beliebigen Objekten erhalten.

+0

Sie brauchen weder die 'new []' noch die 'ToList()', um die Abfrage auszuführen, wenn Sie die Sammlung bei der Erstellung initialisieren können, weil 'obj' dann eine Instanz von' IEnumerable 'ist. Das Problem ist, wenn Sie bei der Erstellung nicht initialisieren können. – derpirscher

+0

Der Autor hat nicht gesagt, dass er die Erstellung nicht initialisieren kann. ToList ist für Fälle, in denen der Autor später weitere Objekte hinzufügen muss. – Evk

Verwandte Themen