In my ASP.Net MVC pages I can click on column headers to sort by that column, but this involves "magic strings" in the aspx, which can result in runtime issues. I am trying to check at runtime whether the values passed to sort by are valid. I have a base class that all my entities inherit from:
Public MustInherit Class BaseEntity(Of T)
'Some Property and method definitions...'
Public Shared Function IsValidSearchProperty(name As String) As Boolean
Dim rootPart As String = name
Dim nested As Boolean = False
If rootPart.Contains(".") Then
rootPart = rootPart.Split("."c)(0)
nested = True
End If
Dim properties As PropertyInfo() = GetType(T).GetProperties()
For Each prop As PropertyInfo In properties
If prop.Name = rootPart Then
If nested Then
'This is where my issue is'
Return Convert.ToBoolean(
prop.PropertyType.InvokeMember("IsValidSearchProperty",
BindingFlags.InvokeMethod Or BindingFlags.Public Or BindingFlags.Static Or BindingFlags.FlattenHierarchy,
Nothing, Nothing, New Object() {name.Substring(name.IndexOf(".") + 1)})
)
Else
Return True
End If
End If
Next
Return False
End Function
End Class
This works great, unless I'm trying to validate a nested property that is more than 1 layer deep in a class hierarchy. For Example:
'Pseudocode Hierarchy
BaseEntity(of T)
PersonEntity : Inherits BaseEntity(Of PersonEntity)
Property FirstName as string
PatientEntity : Inherits PersonEntity
Property PatientType as int
VisitEntity : Inherits BaseEntity(Of VisitEntity)
Property Patient as PatientEntity
Sorting Visits by Patient.FirstName works fine, the property is found recursively, but when I try to sort Visits based on Patient.PatientType, this fails to find the PatientType property. The IsValidSearchProperty is initially called from a VisitEntity, which Finds the Patient property, and it even shows as being of type PatientEntity, but when this method uses InvokeMember to recursively call itself (This is how I am attempting to call it using the property Type), in the second call the GetType(T) is of type PersonEntity, which does not have a PatientType. Any suggestions on how to make this correctly resolve the Type in the nested call?
This method would be called like this:
VisitEntity.IsValidSearchProperty("Patient.FirstName")
VisitEntity.IsValidSearchProperty("Patient.PatientType") '* This one doesn't work
PatientEntity.IsValidSearchProperty("PatientType")
PatientEntity.IsValidSearchProperty("FirstName")
Update
Here is some more on how I'm using this:
Dim sorts() As String = SortExpression.Split(";")
For Each sort As String In sorts
Dim sortParts() As String = sort.Split(" ")
If VisitEntity.IsValidSearchProperty(sortParts(0)) Then
If sortParts(1).ToLower = "true" Then
visits = visits.OrderBy(Of VisitEntity)(sortParts(0).ToString(), SortDirection.Ascending)
Else
visits = visits.OrderBy(Of VisitEntity)(sortParts(0).ToString(), SortDirection.Descending)
End If
Else
_log.WarnFormat("Found invalid sort property {0}", sortParts(0))
End If
Next
SortExpression would be something like "Patient.PatientType True;Patient.FirstName True"