1

此函数使用冒泡算法IO.DirectoryInfoName属性对列表进行排序。

如何在参数中指定要对列表进行排序的属性?

例如:“Drive”、“Name”、“Name.Length”、“Directory.Parent”等...

我认为一个好主意(也许不好,我不知道可以改进多少)是将参数作为字符串传递,然后将字符串转换为...?这是我迷路的地方。

Public Shared Function BubbleSort_List(list As List(Of IO.DirectoryInfo), ByVal SortByProperty As ...) As List(Of IO.DirectoryInfo)
    Return list.Select(Function(s) New With { _
        Key .OrgStr = s, _
        Key .SortStr = System.Text.RegularExpressions.Regex.Replace( _
                       s.Name, "(\d+)|(\D+)", _
                       Function(m) m.Value.PadLeft(list.Select(Function(folder) folder.Name.Length).Max, _
                       If(Char.IsDigit(m.Value(0)), " "c, Char.MaxValue))) _
    }).OrderBy(Function(x) x.SortStr).Select(Function(x) x.OrgStr).ToList

End Function

更新

请注意上面代码的这一部分:

list.Select(Function(folder) folder.Name.Length).Max

我需要的是调用指定我想要的属性而不是“名称”属性的函数。

更新 2

尝试使用@Sriram Sakthivel 解决方案,但它在 [property] 变量中引发关于 UnaryExpression 到 MemberExpression 之间不兼容转换的异常。

    Imports System.Reflection
    Imports System.Linq.Expressions


Private Sub Test(sender As Object, e As EventArgs) Handles MyBase.Shown

    ' Here I create the list
    Dim Folders As List(Of IO.DirectoryInfo) = _
        IO.Directory.GetDirectories("E:\Música\Canciones", "*", IO.SearchOption.TopDirectoryOnly) _
        .Select(Function(p) New IO.DirectoryInfo(p)).ToList()

    ' Here I try to loop the list at the same time I try to sort it, 
    ' specifying the property I want using @Sriram Sakthivel solution,
    ' This part does not work because the second parametter is wrong.
    For Each folderinfo In BubbleSort_List(Folders, Function() Name)
        MsgBox(folderinfo.Name)
    Next

End Sub


    Private Function BubbleSort_List(list As List(Of IO.DirectoryInfo), exp As Expression(Of Func(Of Object))) As List(Of IO.DirectoryInfo)

        Dim [property] As PropertyInfo = DirectCast(DirectCast(exp.Body, MemberExpression).Member, PropertyInfo)

        Return list.Select(Function(s) New With { _
            Key .OrgStr = s, _
            Key .SortStr = System.Text.RegularExpressions.Regex.Replace( _
                           s.Name, "(\d+)|(\D+)", _
                           Function(m) m.Value.PadLeft(list.Select(Function(folder) DirectCast([property].GetValue(folder, Nothing), String).Length).Max(), _
                           If(Char.IsDigit(m.Value(0)), " "c, Char.MaxValue))) _
        }).OrderBy(Function(x) x.SortStr).Select(Function(x) x.OrgStr).ToList

    End Function
4

2 回答 2

1

最多可以使用MemberExpression. obj.Prop.Prop2需要使用UnaryExpression

Private Shared Sub DoSomething(list As List(Of DirectoryInfo), exp As Expression(Of Func(Of Object)))
    Dim member As MemberExpression

    If (TypeOf exp.Body Is UnaryExpression) Then
        member = DirectCast(DirectCast(exp.Body, UnaryExpression).Operand, MemberExpression)
    Else
        member = DirectCast(exp.Body, MemberExpression)
    End If

    Dim [property] As PropertyInfo = DirectCast(member.Member, PropertyInfo)

'You could then use it like
list.Select(Function(folder) DirectCast([property].GetValue(folder, Nothing), String).Length).Max()
End Sub

Private Shared Sub Main()
Dim dir = New DirectoryInfo("somedirectory")
DoSomething(list, Function() dir.Parent)
    DoSomething(list, Function() dir.Name)
    DoSomething(list, Function() dir.FullName)

    DoSomething(list, Function() dir.Parent.Name)'Requires additional effort
End Sub

可能是语法错误。我基本上是 c# 程序员。我刚刚使用了 Vb.net 的转换器工具

编辑:

由于您有目录列表,因此您怀疑如何传递dir.Name参数实际上并不重要, dir.Name 只是传递给PropertyInfo它的捕获。

所以你可以简单地通过New DirectoryInfo("somedirectory").Name。尝试以下

Dim dir = New DirectoryInfo("SomeArbitaryStringIsEnough")

For Each folderinfo In BubbleSort_List(Folders, Function() dir.Name)
    MsgBox(folderinfo.Name)
Next
于 2013-09-29T18:23:54.257 回答
0

如果我正确理解了您想要的内容,Sriram Sakthivel 代码设置了所需内容的一部分,但无法提供您想要的内容。

For Each folderinfo In BubbleSort_List(Folders, "Name")
    MsgBox(folderinfo.Name)
Next

您必须使用目标属性的名称(“Name”、“CreationTime”等)设置字符串类型参数,并通过 ; 从列表项之一(例如第一个)中检索此属性GetProperty;请记住,LINQ 查询是指项目,而不是整个列表。

Private Function BubbleSort_List(list As List(Of IO.DirectoryInfo), propName As String) As List(Of IO.DirectoryInfo)

    Dim curProperty As PropertyInfo = list(0).GetType().GetProperty(propName)

    Return list.Select(Function(s) New With { _
        Key .OrgStr = s, _
        Key .SortStr = System.Text.RegularExpressions.Regex.Replace( _
                       s.Name, "(\d+)|(\D+)", _
                       Function(m) m.Value.PadLeft(list.Select(Function(folder) DirectCast(curProperty.GetValue(folder, Nothing), String).Length).Max(), _
                       If(Char.IsDigit(m.Value(0)), " "c, Char.MaxValue))) _
    }).OrderBy(Function(x) x.SortStr).Select(Function(x) x.OrgStr).ToList

End Function

注意:我只是提议对您的代码进行更正,以使您能够按照我的理解获得所需的内容。我不建议Reflection默认依赖(.GetValue非常慢)。

于 2013-09-29T19:19:59.227 回答