2015-12-22 96 views
0

如何創建能夠將基於MyObject的性質採取在的SortExpression一個通用的方法,這樣的事情:創建匿名LINQ拉姆達排序表達式

void CreateSortedReport(IList<MyObject> list, Expression<Func<MyObject, TSort>> sortExpression, bool ascending = true) 
{ 
    //sort the [list] by sortExpression and by direction; 
} 

,這樣我可以使用它像這樣:

CreateSortedReport(myItems, x=>x.Name); 

CreateSortedReport(myItems, x=>x.CreateDate); 

編輯1: 我之所以問通用的方法,因爲有一些方法,這是非常相似的:

CreateReportSortedByName(myItems) { 
    return myItems.OrderBy(x=>x.Name); 
} 

CreateReportSortedByDate(myItems) { 
    return myItems.OrderBy(x=>x.CreateDate); 
} 
+0

@DioPhung,如果你在'IList的'操作,可以替代使用'Func鍵'你的表達單子。 –

+0

@sstan:沒錯,我想在該方法內部進行就地排序。 –

回答

1

假設MyObject的具體類型,只是一個通用的參數(<TSort>)添加到您的方法簽名:

void CreateReport<TSort>(IList<MyObject> list, Expression<Func<MyObject, TSort>> sortExpression, bool ascending = true) 

如果你想MyObject是一個泛型參數,您的簽名看起來就像這樣:

void CreateReport<MyObject, TSort>(IList<MyObject> list, Expression<Func<MyObject, TSort>> sortExpression, bool ascending = true) 
1

要使用內置排序功能提供就地排序,您需要編寫一個實現IComparer<T>的類。

例如:

class CompareWithDelegate<TOnObject, TSort> : IComparer<TOnObject> 
{ 
    Func<TOnObject, TSort> evaluator; 
    IComparer comparer = Comparer.Default; 
    bool ascending; 
    public CompareWithDelegate(Expression<Func<TOnObject, TSort>> expr, bool ascending = true) 
    { 
     evaluator = expr.Compile(); 
     this.ascending = ascending; 
    } 
    public int Compare(TOnObject left, TOnObject right) 
    { 
     var leftVal = evaluator(left); 
     var rightVal = evaluator(right); 
     return (ascending ? 1 : -1) * comparer.Compare(leftVal, rightVal); 
    } 
} 

然後:

void CreateSortedReport<TSort>(List<MyObject> list, Expression<Func<MyObject, TSort>> sortExpression, bool ascending = true) 
{ 
    list.Sort(new CompareWithDelegate<MyObject, TSort>(sortExpression)); 
    list.Dump();  
} 

注意,list必須List<MyObject>,不IList<MyObject>

或者,如果你不需要它是原地的,你有兩個選擇:

更改簽名Func<MyObject, TSort>

void CreateSortedReport<TSort>(List<MyObject> list, Func<MyObject, TSort> sortExpression, bool ascending = true) 
{ 
    var t = 
     ascending 
     ? list.OrderBy (sortExpression) 
     : list.OrderByDescending(sortExpression); 
} 

或編譯的飛行表達:

void CreateSortedReport<TSort>(List<MyObject> list, Expression<Func<MyObject, TSort>> sortExpression, bool ascending = true) 
{ 
    var method = sortExpression.Compile(); 
    var t = 
     ascending 
     ? list.OrderBy (method) 
     : list.OrderByDescending(method); 
} 
1

您可以建立一個基於內置List(of T).Sort(IComparer(of T))的擴展方法。

public static class SortExtension 
{ 
    public static void SortBy<T, TProperty>(this List<T> list, Func<T, TProperty> orderby, bool ascending = true) 
    { 
     list.Sort(new InnerComparer<T, TProperty>(orderby, ascending)); 
    } 

    class InnerComparer<T, TProperty> : IComparer<T> 
    { 
     private readonly Func<T, TProperty> _property; 
     private readonly int _ascending; 

     public InnerComparer(Func<T, TProperty> property, bool ascending) 
     { 
      _property = property; 
      _ascending = ascending ? 1 : -1; 
     } 

     int IComparer<T>.Compare(T x, T y) 
     { 
      var p1 = _property(x); 
      var p2 = _property(y); 

      return _ascending * Comparer<TProperty>.Default.Compare(p1, p2); 
     } 
    } 
} 

用法:

myObjects.SortBy(o => o.MyProperty);