【问题标题】:Sort all List properties (and subproperties) of an object对对象的所有 List 属性(和子属性)进行排序
【发布时间】:2017-11-13 01:09:45
【问题描述】:

我正在尝试对对象的所有 List 属性进行排序(使用 OrderBy)。它是一个复杂的对象,其列表可能包含列表。我认为反射和递归会让我到达那里,但我似乎在对列表进行实际排序时绊倒了。

这是我的代码:

Private Sub SortData(ByRef obj As Object)
    Dim type As Type = obj.GetType()
    Dim properties As PropertyInfo() = type.GetProperties()

    For Each item As PropertyInfo In properties
        If Not item.PropertyType.FullName.Contains("System.Collection") AndAlso item.PropertyType.FullName.Contains("MyType") Then
            Dim value = obj.GetType().GetProperty(item.Name).GetValue(obj)
            If value IsNot Nothing Then
                SortData(value)
            End If
        End If

        If item.PropertyType.FullName.Contains("System.Collection") Then
            Dim value = obj.GetType().GetProperty(item.Name).GetValue(obj)
            If value IsNot Nothing Then
                Dim subType As Type = value(0).GetType()
                Dim subProperties As PropertyInfo() = subType.GetProperties()
                If subProperties.Any(Function(x) x.Name = "SortKey") Then
                    ' --- Struggling here! ---
                    Dim castList = TryCast(value, List(Of MoreDetail))
                    value = castList.OrderBy(Function(x) x.SortKey)
                    value = TryCast(value, List(Of MoreDetail))
                    ' --- End struggle ---
                End If

                For Each subProperty In subProperties
                    SortData(value.GetType().GetProperty(subProperty.Name).GetValue(value))
                Next
            End If
        End If
    Next

End Sub

主要问题在于代码的“在这里挣扎”部分 - 我似乎必须将对象转换为其原始类型,但这违背了反射的目的,因为不同的对象将具有不同的列表类型,所以理想情况下,我可以根据其反射类型投射对象。

感谢您的帮助!

编辑:为了缓解我的问题中的“XY 问题”,这就是我正在尝试做的事情......我希望能够对对象的所有 List 属性进行排序 - 问题是对象可以嵌套列表,所以理想情况下我会通过反射来做到这一点,递归地检查列表是否包含任何子属性中的列表。列表大多是复杂类型,所以我只想在集合包含定义了“SortKey”属性的对象时对列表进行排序。

编辑2:我所追求的一个例子是(伪代码):

Public Class SuperList
    Public Property A As String = ""
    Public Property BList As New List(Of B)
End Class

Public Class B
   Public Property SortKey As String = ""
   Public Property Name As String = ""
   Public Property CList As New List(Of C)
End Class

Public Class C
   Public Property SortKey As String = ""
   Public Property Name As String = ""
End Class

Dim cExampleSecond As New C With {.SortKey = "345", .Name = "C Second"}
Dim cExampleFirst As New C With {.SortKey = "123", .Name = "C First"}
Dim BExampleFirst As New B With {.Sortkey = "ABC", .Name = "B First"}
BExampleFirst.CList.Add(cExampleSecond)
BExampleFirst.CList.Add(cExampleFirst)
Dim superExample As New SuperList With {.A = "Whatever"}
superExample.BList.Add(BExampleFirst)

...
SortData(superExample)
...

运行 SortData() 后应该如下所示:

superExample = 
   .A = "Whatever"
   .BList = 
      .SortKey = "ABC"
      .BExampleFirst = 
         cExampleFirst = 
            .SortKey = "123" 
            .Name = "C First"
         cExampleSecond = 
            .SortKey = "345" 
            .Name = "C Second"

请注意,如果 superExample.BList 有更多元素,它们也会被排序...

【问题讨论】:

  • 听起来像XY problem
  • 给出你希望得到的输入和输出的例子。
  • @Plutonix 谢谢 - 我已经对问题进行了更多编辑(在底部),以了解我想要实现的目标
  • @Han 好的,我会编辑一下

标签: vb.net sorting reflection


【解决方案1】:

看看你的例子,我认为你想对一种树进行排序。

1- 树意味着递归:SortData() 将对当前级别/当前列表进行排序,并为每个子元素调用 SortData()。您可以使用继承或组合在树的每个元素中实现此功能。

2- 您可以使用ListDictionarysort 功能。您只需为列表中的元素实现 IComparable。

这是一些说明全局方法的示例代码。

Public Class SortedElem

    Implements IComparable(Of SortedElem)
    Public Property Children As New List(Of SortedElem)
    Public Property SortKey As String

    Public Sub SortData()
        Children.Sort()
        For Each child In Children
            child.Children.Sort()
        Next
    End Sub

    Public Function CompareTo(other As SortedElem) As Integer Implements IComparable(Of SortedElem).CompareTo
        Return String.Compare(Me.SortKey, other.SortKey)
    End Function

End Class

Public Class SuperList
    Inherits SortedElem
    Public Property A As String = ""
End Class

Public Class B
    Inherits SortedElem
    Public Property Name As String = ""

End Class

Public Class C
    Inherits SortedElem
    Public Property Name As String = ""
End Class

Public Sub AnySub()

    Dim cExampleFirst As New C With {.SortKey = "1", .Name = "C First"}
    Dim cExampleSecond As New C With {.SortKey = "3", .Name = "C Second"}
    Dim cExampleThird As New C With {.SortKey = "2", .Name = "C Third"}

    Dim BExampleFirst As New B With {.SortKey = "ABC", .Name = "B First"}
    Dim BExampleSecond As New B With {.SortKey = "XYZ", .Name = "B Second"}
    Dim BExampleThird As New B With {.SortKey = "DEF", .Name = "B Third"}

    BExampleFirst.Children.Add(cExampleFirst)
    BExampleFirst.Children.Add(cExampleSecond)
    BExampleFirst.Children.Add(cExampleThird)

    Dim superExample As New SuperList With {.A = "Whatever"}
    superExample.Children.Add(BExampleFirst)
    superExample.Children.Add(BExampleSecond)
    superExample.Children.Add(BExampleThird)

    superExample.SortData()

End Sub

【讨论】:

  • 谢谢 - 这看起来像是一个选项,但这需要对类进行大量更改,以便它们都继承自该主类。就我而言,这可能不是最好的解决方案,但我很快就会尝试一下!
猜你喜欢
  • 2016-02-08
  • 1970-01-01
  • 2015-06-20
  • 2023-03-27
  • 1970-01-01
  • 2012-04-26
  • 1970-01-01
  • 2020-08-03
相关资源
最近更新 更多