Entwickler-Ecke
Basistechnologien - Sortieren von IEnumerable ?
Biplane - Mo 17.11.08 16:06
Titel: Sortieren von IEnumerable ?
Moinmoin,
derzeit kämpfe ich mit dem Problem der dynamischen Sortierung eines IEnumarable herum...
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| List<Daten> wertList = new List<daten>(); wertList.Add(new Daten{ wert = "test5"}); wertList.Add(new Daten{ wert = "test3"}); wertList.Add(new Daten{ wert = "test2"}); wertList.Add(new Daten{ wert = "test7"});
var x = wertList.OrderBy("wert", true);
foreach (var c in x) { System.Diagnostics.Debug.WriteLine(c.wert); } |
Dieses Beispiel funktioniert (zusammen mit untenstehendem Quellcode) einwandfrei, solange "wertList" vom Typ "List<Daten>" oder "IEnumerable<Daten>" ist.
Das Problem ist aber, das ich in meinem Assembly, wo dieser Quellcode ausgeführt werden soll, nicht den Typ "Daten" kenne, sondern nur auf IEnumerable (var wertList = daten as IEnumerable) konvertieren kann. Bei IEnumerable funktionieren aber die Erweiterungsmethoden nicht.
Kennt jemand eine Lösung ? Im Zweifelsfall zur not auch ohne LinqToObjects.
Gruß
Norbert
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31:
| public static class DynamicEnumerable { public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> query, string propertyName, bool ascending) { ParameterExpression prm = System.Linq.Expressions.Expression.Parameter(typeof(T), "it");
System.Linq.Expressions.Expression property = System.Linq.Expressions.Expression.Property(prm, propertyName);
Type propertyType = property.Type;
MethodInfo method = typeof(DynamicEnumerable).GetMethod("OrderByProperty", BindingFlags.Static | BindingFlags.NonPublic) .MakeGenericMethod(typeof(T), propertyType);
return (IEnumerable<T>)method.Invoke(null, new object[] { query, prm, property, ascending }); }
private static IEnumerable<T> OrderByProperty<T, P>(this IEnumerable<T> query, ParameterExpression prm, System.Linq.Expressions.Expression property, bool ascending) { Func<IEnumerable<T>, Func<T, P>, IEnumerable<T>> orderBy = (q, p) => ascending ? q.OrderBy(p) : q.OrderByDescending(p); return orderBy(query, System.Linq.Expressions.Expression.Lambda<Func<T, P>>(property, prm).Compile()); } }
class Daten { public string wert { get; set; } } |
Moderiert von
Christian S.: C#-Tags hinzugefügt
Kha - Mo 17.11.08 17:45
Titel: Re: Sortieren von IEnumerable ?
Biplane hat folgendes geschrieben : |
| Das Problem ist aber, das ich in meinem Assembly, wo dieser Quellcode ausgeführt werden soll, nicht den Typ "Daten" kenne, sondern nur auf IEnumerable (var wertList = daten as IEnumerable) konvertieren kann. |
Weshalb? Hört sich für mich nicht ganz sinnig an.
Wie auch immer: Nach einem
.Cast<object>() solltest du auch IEnumerables an deine Methode schicken können.
Biplane - Mo 17.11.08 18:15
Hmm...
Folgende Varianten habe ich schon ausprobiert...
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var variante1 = _List.Cast<object>();
IEnumerable variante2 = _List as IEnumerable;
IEnumerable<object> variante2 = _List as IEnumerable<object>; |
Das ganze verwende ich in einer Assembly mit UserControls. Die Daten aus der Liste werden mittels Reflection bei einem TreeControl verwendet. Dies funktioniert prima, nur soll noch innerhalb einer Ebene/Ordner nach der anzuzeigenden Spalte sortiert werden.
So einfach scheint es wohl doch nicht zu sein.
Gruß
Norbert
Moderiert von
Christian S.: C#-Tags hinzugefügt
Kha - Mo 17.11.08 18:50
Biplane hat folgendes geschrieben : |
|
Jupp, nach weiterem Nachdenken ;) logisch. Wenn du nicht für jedes Item Reflection aufrufen willst (was in der GUI wahrscheinlich sogar noch erträglich sein sollte?),
muss dein OrderBy-Ersatz (egal ob mit Linq oder nicht) den Typ der Liste kennen, also z.B. durch einen weiteren
Type-Parameter. Oder du lässt die Quellen deiner dynamischen Listen IQueryable zurückgeben (.AsQueryable), denn dafür gibts schon fertige Lösungen:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Biplane - Di 18.11.08 10:14
Tja, das Problem bleibt unabhängig von IQueryable oder IEnumerable gleich. Der Quelltext von deinem Linq "static class DynamicQueryable" ist grundsätzlich die gleiche vorgehensweise, die ich im Initialbeitrag mit "DynamicEnumerable" gegangen bin. Das funktioniert so leider nicht. Ohne bekannten Typ, kommt man wohl nicht an die zu sortierende Spalte ran.
Zwei mögliche Lösugen fallen mir noch ein:
1. Einen größer-Operator implementieren, der intern über Reflection auf die zu Sortierende Spalte zugreift und dann drum herum einen Sortieralgorhytmus bauen.
2. Die Verfügbare Liste (IEnumerable) in eine, dem Assembly bekannte, Klasse zu überführen:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| class Sorthelper { public Sorthelper(Object object, String column) {
} public String Wert { get; set; } } |
Eine Liste von Sorthelper läst sich dann einfach sortieren.
Gruß
Norbert
Moderiert von
Kha: C#-Tags hinzugefügt
Kha - Di 18.11.08 14:42
Biplane hat folgendes geschrieben : |
| Tja, das Problem bleibt unabhängig von IQueryable oder IEnumerable gleich. |
Nein, IQueryable ist immer mit einem Typ verbunden (nämlich IQueryable.ElementType). Ich bin davon ausgegangen, dass
irgendwo vor dem TreeView die Daten als IEnumerable<T> vorliegen, du sie also dort in IQueryable konvertieren kannst.
Biplane hat folgendes geschrieben : |
Zwei mögliche Lösugen fallen mir noch ein:
1. Einen größer-Operator implementieren, der intern über Reflection auf die zu Sortierende Spalte zugreift und dann drum herum einen Sortieralgorhytmus bauen.
2. Die Verfügbare Liste (IEnumerable) in eine, dem Assembly bekannte, Klasse zu überführen: |
Also mit Reflection pro Item? Dann kannst du auch Linq2Objects benutzen:
C#-Quelltext
1: 2: 3: 4: 5: 6:
| public static IEnumerable OrderByProperty(this IEnumerable self, string propertyName) { return self.Cast<object>() .OrderBy(o => o.GetType().GetProperty(propertyName).GetValue(o, null)); } |
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!