I\'m trying to build some code for dynamically sorting a Linq IQueryable<>.
The obvious way is here, which sorts a list using a string for the field name
http
I liked the work above - thank you very much! I took the liberty to add a couple things:
Added sort direction.
Made registering and calling two different concerns.
Usage:
var censusSorter = new Sorter();
censusSorter.AddSortExpression("SubscriberId", e=>e.SubscriberId);
censusSorter.AddSortExpression("LastName", e => e.SubscriberId);
View.CensusEntryDataSource = censusSorter.Sort(q.AsQueryable(),
new Tuple("SubscriberId", SorterSortDirection.Descending),
new Tuple("LastName", SorterSortDirection.Ascending))
.ToList();
internal class Sorter
{
public Sorter()
{
}
public void AddSortExpression(string name, Expression> selector)
{
// Register all possible types of sorting for each parameter
firstPasses.Add(name, s => s.OrderBy(selector));
nextPasses.Add(name, s => s.ThenBy(selector));
firstPassesDesc.Add(name, s => s.OrderByDescending(selector));
nextPassesDesc.Add(name, s => s.OrderByDescending(selector));
}
public IOrderedQueryable Sort(IQueryable list,
params Tuple[] names)
{
IOrderedQueryable result = null;
foreach (var entry in names)
{
result = result == null
? SortFirst(entry.Item1, entry.Item2, list)
: SortNext(entry.Item1, entry.Item2, result);
}
return result;
}
private IOrderedQueryable SortFirst(string name, SorterSortDirection direction,
IQueryable source)
{
return direction == SorterSortDirection.Descending
? firstPassesDesc[name].Invoke(source)
: firstPasses[name].Invoke(source);
}
private IOrderedQueryable SortNext(string name, SorterSortDirection direction,
IOrderedQueryable source)
{
return direction == SorterSortDirection.Descending
? nextPassesDesc[name].Invoke(source)
: nextPasses[name].Invoke(source);
}
private readonly FirstPasses firstPasses = new FirstPasses();
private readonly NextPasses nextPasses = new NextPasses();
private readonly FirstPasses firstPassesDesc = new FirstPasses();
private readonly NextPasses nextPassesDesc = new NextPasses();
private class FirstPasses : Dictionary, IOrderedQueryable>> { }
private class NextPasses : Dictionary, IOrderedQueryable>> { }
}