具有通用memberepressation的多个排序

时间:2011-05-20 16:22:32

标签: asp.net vb.net linq

编辑2019-01-31:Latest solution

我已经按照示例herehere创建了一个带有memberexpressions的泛型排序,但我无法弄清楚我应该如何添加“ThenBy”子句,或者组合多个用于在methodcallexpression中排序的列。理想情况下,ThenBy应该在跳过之前进行,但它不能,因为它无法看到我使用methodcallexpression创建的orderby子句。 GridSortExpression是一个Telerik类 - 它只描述了查询应该排序的列和方向。

任何人都能解开一些光明吗?这就是我现在所拥有的:

Dim exp As Expressions.Expression(Of Func(Of Product_Catalog, Boolean)) = PredicateBuilder.True(Of Product_Catalog)()
exp = exp.And(Function(e) e.Chapter_Price > 30)
Dim sortExpression As New List(Of GridSortExpression)({New GridSortExpression() With {.SortOrder = GridSortOrder.Descending, .FieldName = "Id"}})
If sortExpression.Count = 0 Then
     catalogList = con.Product_Catalogs.AsExpandable.Where(exp).OrderBy(Function(o) o.Item_Type).ThenBy(Function(o) o.Item_Description).Skip(startRowIndex).Take(maximumRows).ToList
Else
     Dim param As ParameterExpression = Expression.Parameter(GetType(Product_Catalog), String.Empty)
     Dim prop As MemberExpression = Expression.PropertyOrField(param, sortExpression(0).FieldName)
     Dim sort As LambdaExpression = Expression.Lambda(prop, param)
     Dim source = con.Product_Catalogs.AsExpandable.Where(exp)
     Dim resultExp As MethodCallExpression
     resultExp = Expression.[Call](GetType(Queryable), "OrderBy" & If(sortExpression(0).SortOrder = GridSortOrder.Descending, "Descending", ""), _
         New Type() {GetType(Product_Catalog), prop.Type}, con.Product_Catalogs.AsExpandable.Where(exp).Expression, Expression.Quote(sort))

     catalogList = source.Provider.CreateQuery(Of Product_Catalog)(resultExp).Skip(startRowIndex).Take(maximumRows).ToList
End If

2 个答案:

答案 0 :(得分:1)

这是一种非常通用的方法来进行属性排序,而不必为每种稍微不同的排序实现多个排序比较器。

它将允许任意数量的排序“列”(尽管您需要稍微增强以支持不同的排序方向)

缺点是它显然不是最有效的,尽管使用调用代理比使用反射更有效。您还需要定义可能要排序的对象属性的常规函数​​。通过使其更具体对象,您可以修复该方面...

Public Class PropertySortComparer
Implements IComparer

Public Delegate Function GetProp(ByVal obj As Object) As Object
Public SortProps As New List(Of GetProp)

Public Sub New(ParamArray SortMethods() As GetProp)
    Me.SortProps.AddRange(SortMethods)
End Sub

Public Function Compare(x As Object, y As Object) As Integer Implements System.Collections.IComparer.Compare
    For Each gp As GetProp In SortProps
        Dim xVal As Object = gp.Invoke(x)
        Dim yVal As Object = gp.Invoke(y)
        If xVal > yVal Then
            Return 1
        ElseIf xVal < yVal Then
            Return -1
        Else
            'next loop does next property
        End If
    Next
    Return 0
End Function
End Class

Public Module module1
Sub test()
    Dim buffer As New List(Of Rectangle)
    buffer.Add(New Rectangle(34, 55, 40, 30))
    buffer.Add(New Rectangle(34, 55, 45, 38))
    buffer.Add(New Rectangle(34, 56, 46, 30))
    buffer.Add(New Rectangle(34, 70, 45, 30))

    Dim Lst() As Rectangle = buffer.ToArray
    Array.Sort(Lst, New PropertySortComparer(AddressOf Left, AddressOf Top, AddressOf Widht))
    'Lst is now sorted by Left, Top, Width
End Sub

Public Function Left(r As Object) As Object
    Return r.Left
End Function

Public Function Top(r As Object) As Object
    Return r.Top
End Function

Public Function Widht(r As Object) As Object
    Return r.Width
End Function

End Module

答案 1 :(得分:0)

您是否尝试进行排序,有一天您可以根据1个属性进行排序, 然后在另一天,排序可能基于2个或更多属性?

如果是这样,您可能需要使用反射来获取属性的数量,然后根据它们的TYPE对它们进行排序。如果您的目标是能够根据任意数量的属性进行排序,这是一个有趣的想法。但是,如果其中一个属性的TYPE是另一个CLASS,那么呢?

我想你可能需要看一下

实施IComparable

为了构建自己的例行程序来进行排序。

这里有一个使用它的例子:&gt;&gt;

http://msdn.microsoft.com/en-us/library/4d7sx9hd(VS.80).aspx

但是,这将特定于您创建的每个类。