Sorting with column name
文章目錄
隨手筆記
IQueryable和IEumerable相信是很多開發人員常用到的類別,並配合linq或是lambda來做資料處理,
不過每當資料要呈現時,總免不要排個序取個分頁,當欄位是固定的時候或許還能這樣寫
var query = data.OrderBy(p=>p.col1);
不過如果欄位很多樣的時侯就糗了,尤其當要排序的欄位是從client送上來的,多半會傳欄位名稱,無技可施的情況下你可能會寫出這樣的程式碼
switch(colname){
case col1:
query = data.OrderBy(p=>p.col1);
break;
case col2:
query = data.OrderBy(p=>p.col2);
break;
......
default:
query = data.OrderBy(p=> p.id);
}
這時侯你就會希望linq本身提供的排序要是也能吃欄位名稱就好了…
當然我也是不例外,linq不吃字串排序使用起來實在是太不直覺了,還好皇天不負苦心人,終於讓我在google,stackoverflow的問題海中找到了,這篇主要就是要記錄這段短小精悍的程式碼,不過一開始提到的IQueryable和IEumerable的實作上是有一些差異,不囉嗦看程式碼
public static class LinqExtensions
{
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName)
{
return (IOrderedQueryable<T>)OrderBy((IQueryable)source, propertyName);
}
public static IQueryable OrderBy(this IQueryable source, string propertyName)
{
var x = Expression.Parameter(source.ElementType, "x");
var selector = Expression.Lambda(Expression.PropertyOrField(x, propertyName), x);
return source.Provider.CreateQuery(
Expression.Call(typeof(Queryable),
"OrderBy",
new Type[] { source.ElementType, selector.Body.Type },
source.Expression, selector));
}
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string propertyName)
{
return (IOrderedQueryable<T>)OrderByDescending((IQueryable)source, propertyName);
}
public static IQueryable OrderByDescending(this IQueryable source, string propertyName)
{
var x = Expression.Parameter(source.ElementType, "x");
var selector = Expression.Lambda(Expression.PropertyOrField(x, propertyName), x);
return source.Provider.CreateQuery(
Expression.Call(typeof(Queryable),
"OrderByDescending",
new Type[] { source.ElementType, selector.Body.Type },
source.Expression, selector));
}
}
有了這個上面這段程式碼就可以直接寫成
var query = data.OrderBy(colname);
網路上有很多種寫法,不過這種目前應該是最佳解,理由是,很多的OrderBy的寫法都是直接回傳IQueryable,而直接回傳IQueryable也沒有不好,不過你會無法接著使用ThenBy、ThenByDescending的方法。另外,當你將IQueryable實體化的時候,資料就變成了List,但是很多時候你要排序的結果都是List Array,而上面的方法就無法使用了,因此我就依樣畫葫替IEnumerable寫一段請小心服用,
public static class LinqExtensions
{
public static IOrderedEnumerable<TSource> OrderBy<TSource>
(this IEnumerable<TSource> source, string propertyName)
{
PropertyInfo prop = typeof(TSource).GetProperty(propertyName);
if (prop == null)
{
throw new Exception("No property '" + propertyName + "' in + " + typeof(TSource).Name + "'");
}
return source.OrderBy(x => prop.GetValue(x, null));
}
public static IOrderedEnumerable<TSource> OrderByDescending<TSource>
(this IEnumerable<TSource> source, string propertyName)
{
PropertyInfo prop = typeof(TSource).GetProperty(propertyName);
if (prop == null)
{
throw new Exception("No property '" + propertyName + "' in + " + typeof(TSource).Name + "'");
}
return source.OrderByDescending(x => prop.GetValue(x, null));
}
}
藉由這兩個擴充方法,你就可以在linq中展現各種排序神技。(GitHub)