What I used to do is create a case swi开发者_运维技巧tch that sorts my LINQ in this format:
List<products> productList = GetAllLists();
switch (sortBy)
{
case "name":
return productsList.OrderBy(pl => pl.Name);
case "date":
return productsList.OrderBy(pl => pl.DateCreate);
}
which, in the long run, becomes cumbersome.
I wanted to have a generic method that you simply use to sort out List collections like these and will help you toggle which property to sort by.. something like this:
return SortListCollection(productsList, Name);
You don't need to use reflection for this, you can do it using expression trees, which will be much faster. Here's a blog post that describes the process, but a cut'n'paste sample is:
public static IQueryable<T> SortBy<T>(this IQueryable<T> source, string propertyName)
{
var parameter = Expression.Parameter(source.ElementType, String.Empty);
var property = Expression.Property(parameter, propertyName);
var lambda = Expression.Lambda(property, parameter);
var methodCallExpression = Expression.Call(typeof(Queryable), "OrderBy",
new Type[] { source.ElementType, property.Type },
source.Expression, Expression.Quote(lambda));
return source.Provider.CreateQuery<T>(methodCallExpression);
}
Do you need to be able to pass in strings? Passing in a Func<T,TResult>
delegate will be fast, flexible, and allow runtime checking; passing in a string
won't be.
You could even have a bunch of predefined delegates ready-to-go:
var sortedByName = productList.OrderBy(NameSelector);
var sortedByDate = productList.OrderBy(DateCreatedSelector);
var sortedByCustom = productList.OrderBy(p => p.SomeOtherProperty);
// ...
// predefined delegates
public static readonly Func<Product, string> NameSelector = p => p.Name;
public static readonly Func<Product, DateTime> DateCreatedSelector =
p => p.DateCreated;
And, of course, you could wrap it all up in your own method if you wanted to, but that method would be a superfluous one-liner just wrapping the OrderBy
call.
Solved:
private List<T> SortList<T>(List<T> collection, SortOrder order, string propertyName) where T : class
{
if (order == SortOrder.Descending)
{
return collection.OrderByDescending(cc => cc.GetType().GetProperty(propertyName).GetValue(cc, null)).ToList();
}
return collection.OrderBy(cc => cc.GetType().GetProperty(propertyName).GetValue(cc, null)).ToList();
}
Use reflection to build a comparer class that can compare by property name. Then instantiate this class and pass it's compare function to List.Sort
精彩评论