2 Stimmen

Eine Liste nach einem beliebigen Sortierausdruck ordnen?

Pregunta:

Ich habe eine allgemeine Liste, etwa diese:

System.Collections.Generic.List<Question> myquestions = new System.Collections.Generic.List<Question>();

Und ich habe ein Paging-Beispiel, mit einer LINQ-Tabelle aus der Datenbank akquiriert, tun dies für Paging:

var questions = context.Questions
    .OrderBy(sidx + " " + sord)
    .Skip(pageIndex * pageSize)
    .Take(pageSize);

Im Moment habe ich für das Blättern in der Codeliste die folgenden Möglichkeiten:

var questionss = myquestions
    .OrderBy(x => x.Id)
    .Skip(pageIndex * pageSize)
    .Take(pageSize);

Und was ich möchte, ist die Möglichkeit, "myquestions" nach einer Zeichenkette wie im obigen Beispiel zu ordnen. Ist das möglich?

3voto

Guffa Punkte 663241

Dank der "Lazy Execution" können Sie die Erweiterungsmethoden in separaten Anweisungen verketten, was bedeutet, dass Sie je nach Bedingung unterschiedliche Sortierungen hinzufügen können:

IOrderedQueryable<Question> sorted;
switch (sort) {
  case "Id":  sorted = myquestions.OrderBy(x => x.Id);
  case "Name": sorted = myquestions.OrderBy(x => x.Name);
  case "Size": sorted = myquestions.OrderBy(x => x.Size);
  case "Id Desc":  sorted = myquestions.OrderByDescending(x => x.Id);
  case "Name Desc": sorted = myquestions.OrderByDescending(x => x.Name);
  case "Size Desc": sorted = myquestions.OrderByDescending(x => x.Size);
  default: throw new NotImplementedException();
}
var questions = sorted.Skip(pageIndex * pageSize).Take(pageSize);

Sie können sogar eine zweite Sortierung hinzufügen (oder so viele, wie Sie möchten, nach der ersten sind sie alle gleich):

IOrderedQueryable<Question> sorted;
switch (sort) {
  case "Id":  sorted = myquestions.OrderBy(x => x.Id);
  case "Name": sorted = myquestions.OrderBy(x => x.Name);
  case "Size": sorted = myquestions.OrderBy(x => x.Size);
  case "Id Desc":  sorted = myquestions.OrderByDescending(x => x.Id);
  case "Name Desc": sorted = myquestions.OrderByDescending(x => x.Name);
  case "Size Desc": sorted = myquestions.OrderByDescending(x => x.Size);
  default: throw new NotImplementedException();
}
switch (sort2) {
  case "Id":  sorted = sorted.ThenBy(x => x.Id);
  case "Name": sorted = sorted.ThenBy(x => x.Name);
  case "Size": sorted = sorted.ThenBy(x => x.Size);
  case "Id Desc":  sorted = sorted.ThenByDescending(x => x.Id);
  case "Name Desc": sorted = sorted.ThenByDescending(x => x.Name);
  case "Size Desc": sorted = sorted.ThenByDescending(x => x.Size);
}
var questions = sorted.Skip(pageIndex * pageSize).Take(pageSize);

3voto

Stefan Steiger Punkte 72861

Hahaha, jetzt fange ich an zu weinen:

Beim Versuch, die Lösung von dtb umzusetzen, habe ich das Problem erkannt:

OrderByField<T>(IQueryable<T> q,

Gibt IQueryable bei der Eingabe von IQueryable... lol bs. Also, die eigentliche Frage ist, wie man Liste konvertieren, um iQueryable sein.

Das ist in der Tat ganz einfach:

var list = new List<T>(); 
var queryable = list.AsQueryable(); 

puis

queryable.OrderBy(sidx + " " + sord);

Die endgültige Lösung ist also so trivial wie:

myquestions.AsQueryable().OrderBy(sidx + " " + sord).Skip(pageIndex * pageSize).Take(pageSize);

Das bedeutet auch, dass Linq.Table IQueryable implementiert, was IMHO Sinn macht.

Edita:
Anmerkung:
Dies erfordert eine Bezugnahme auf: Dynamic.dll (nicht System.Dynamic.dll) sowie

using System.Linq.Dynamic;

Wenn Sie Dynamic.dll nicht referenzieren oder die using-Direktive nicht deklarieren, erhalten Sie einen Fehler bei AsQueryable().

2voto

Cheng Chen Punkte 40879

Bitte prüfen meine Antwort auf eine andere Frage wie man eine benutzerdefinierte OrderBy Prädikat mit Expression von einer bestimmten String .

1voto

Jon Skeet Punkte 1325502

Eine Möglichkeit besteht darin, ein Wörterbuch von jeder möglichen Bestellzeichenfolge zu einem entsprechenden Delegaten zu erstellen. Zum Beispiel:

Dictionary<string, Func<IEnumerable<Question>, IEnumerable<Question>> orderings =
    new Dictionary<string, Func<IEnumerable<Question>, IEnumerable<Question>>()
{
    { "Id",  questions => questions.OrderBy(x => x.Id) },
    { "Title",  questions => questions.OrderBy(x => x.Title) },
    { "Answer",  questions => questions.OrderBy(x => x.Answer) },
    { "Id Desc",  questions => questions.OrderByDescending(x => x.Id) },
    { "Title Desc",  questions => questions.OrderByDescending(x => x.Title) },
    { "Answer Desc",  questions => questions.OrderByDescending(x => x.Answer) },
};

Dann können Sie diese Zuordnung zur Ausführungszeit finden und die Funktion anwenden.

1voto

Niki Punkte 15426

Sie können sich ansehen Dynamisches Linq . IIRC es war eine Probe, die mit VS2008 geliefert, ich bin nicht 100% sicher, ob es noch in VS2010 enthalten ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X