具有通用memberepressation的多个排序

dtr*_*yan 6 linq vb.net asp.net

编辑2019-01-31:最新解决方案

我已经按照这里这里的示例创建了一个带有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
Run Code Online (Sandbox Code Playgroud)

Dar*_*nMB 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
Run Code Online (Sandbox Code Playgroud)