Imports System.Collections.Generic Imports System.Reflection Imports System.Text.RegularExpressions Public Class PropertyValues Private Shared _indexPattern = "\((\d+)\)" Private Shared _indexRegex As New Regex(_indexPattern) Public Shared Function GetPropValues(Obj As Object, PropertyName As String) Dim oResult As Object = GetPropValue(Obj, PropertyName) ' Wrap the result of `GetPropValue` in a list if a single Value is returned If TypeOf oResult Is List(Of Object) Then Return oResult Else Return New List(Of Object) From {oResult} End If End Function Public Shared Function GetPropValue(Obj As Object, PropertyName As String) Dim oNameParts As String() = PropertyName.Split("."c) If IsNothing(Obj) Then Return Nothing End If If oNameParts.Length = 1 Then Return Obj.GetType().GetProperty(PropertyName).GetValue(Obj, Nothing) End If For Each oPart As String In oNameParts Dim oType As Type = Obj.GetType() Dim oPartName = oPart Dim oIndex As Integer = Nothing Dim oHasIndex As Boolean = HasIndex(oPartName) If oHasIndex Then oPartName = StripIndex(oPart) oIndex = GetIndex(oPart) End If Dim oInfo As PropertyInfo = oType.GetProperty(oPartName) If IsNothing(oInfo) Then Return Nothing End If If IsNothing(oInfo.GetValue(Obj, Nothing)) Then Return Nothing End If Obj = oInfo.GetValue(Obj, Nothing) If oHasIndex Then Obj = Obj(0) End If If IsArray(Obj) And Not oHasIndex Then Dim oCurrentPart As String = oPart Dim oSplitString As String() = New String() {"." & oCurrentPart & "."} Dim oPathFragments = PropertyName.Split(oSplitString, StringSplitOptions.None) Dim oResults As New List(Of Object) ' if path has no more subitems, return an empty list If oPathFragments.Length = 1 Then Return oResults End If For Each oArrayItem In Obj Dim oResult = GetPropValue(oArrayItem, oPathFragments(1)) If Not IsNothing(oResult) Then oResults.Add(oResult) End If Next Return oResults End If Next Return Obj End Function Private Shared Function GetIndex(Prop As String) As Integer If Regex.IsMatch(Prop, _indexPattern) Then Dim oMatch = _indexRegex.Match(Prop) Dim oGroup = oMatch.Groups.Item(1) Dim oValue = oGroup.Value Return Integer.Parse(oValue) End If Return Nothing End Function Private Shared Function StripIndex(Prop As String) As String Return Regex.Replace(Prop, _indexPattern, "") End Function Private Shared Function HasIndex(Prop As String) As Boolean Return Regex.IsMatch(Prop, _indexPattern) End Function End Class