| Autor |
Beitrag |
Biplane
Hält's aus hier
Beiträge: 9
|
Verfasst: Mo 17.11.08 16:06
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
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
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mo 17.11.08 17:45
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 
Hält's aus hier
Beiträge: 9
|
Verfasst: 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
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mo 17.11.08 18:50
Biplane hat folgendes geschrieben : | C#-Quelltext |
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: weblogs.asp.net/scot...c-query-library.aspx
_________________ >λ=
|
|
Biplane 
Hält's aus hier
Beiträge: 9
|
Verfasst: 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
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Di 18.11.08 14:42
|
|
|