创建匿名LINQ拉姆达排序表达式

问题描述:

如何创建能够将基于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:没错,我想在该方法内部进行就地排序。 –

假设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) 

要使用内置排序功能提供就地排序,您需要编写一个实现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); 
} 

您可以建立一个基于内置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);