The properties are always going to come back that way because that's how the Type class is implemented. GetProperties will return properties declared in the specific type under investigation first, then it's direct base class, then the base class of that and so on. If you want to access them in a different order then you need to either call GetProperties multiple times with different BindingFlags values or else sort the result from a single call to GetProperties. Here are some examples:
vb.net Code:
Module Module1
Sub Main()
Dim gc As New Grandchild
Dim gcType = gc.GetType()
Dim properties = gcType.GetProperties()
For Each propertyInfo In properties
Console.WriteLine($"{propertyInfo.DeclaringType.Name}.{propertyInfo.Name}")
Next
End Sub
End Module
Public Class Parent
Public Property A As String
Public Property D As String
End Class
Public Class Child
Inherits Parent
Public Property B As String
Public Property E As String
End Class
Public Class Grandchild
Inherits Child
Public Property C As String
Public Property F As String
End Class
Output:
Grandchild.C
Grandchild.F
Child.B
Child.E
Parent.A
Parent.D
vb.net Code:
Dim gc As New Grandchild
Dim gcType = gc.GetType()
Dim properties = gcType.GetProperties().OrderBy(Function(pi) If(pi.DeclaringType Is pi.ReflectedType, 1, 0))
For Each propertyInfo In properties
Console.WriteLine($"{propertyInfo.DeclaringType.Name}.{propertyInfo.Name}")
Next
Output:
Child.B
Child.E
Parent.A
Parent.D
Grandchild.C
Grandchild.F
Note that, in this case, inherited properties are listed first and directly declared properties are listed last, but properties declared in the direct base class are still listed before those in base classes further up the hierarchy. If that's OK then this is all you need. If you want to fully reverse the order then you'll need a bit more than that. This will do the job:
vb.net Code:
Imports System.Reflection
Imports System.Runtime.CompilerServices
Module Module1
Sub Main()
Dim gc As New Grandchild
Dim gcType = gc.GetType()
Dim properties = gcType.GetProperties().OrderByDescending(Function(pi) pi.GetDeclarationDepth())
For Each propertyInfo In properties
Console.WriteLine($"{propertyInfo.DeclaringType.Name}.{propertyInfo.Name}")
Next
End Sub
End Module
Public Module PropertyInfoExtensions
<Extension>
Public Function GetDeclarationDepth(source As PropertyInfo) As Integer
Dim derivedType = source.ReflectedType
Dim baseType = source.DeclaringType
Dim depth = 0
Do Until derivedType Is baseType
depth += 1
derivedType = derivedType.BaseType
Loop
Return depth
End Function
End Module
Output:
Parent.A
Parent.D
Child.B
Child.E
Grandchild.C
Grandchild.F