在我的ASP.Net MVC页面中,我可以单击列标题按该列排序,但这涉及到aspx中的“魔术字符串”,这可能导致运行时问题。我试图在运行时检查传递给sort by的值是否有效。我有一个基类,我的所有实体都继承自:
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
这非常有用,除非我试图验证类层次结构中超过1层深的嵌套属性。例如:
'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
通过Patient.FirstName排序访问工作正常,递归地找到属性,但是当我尝试基于Patient.PatientType对访问进行排序时,无法找到PatientType属性。 IsValidSearchProperty最初是从VisitEntity调用的,它发现了Patient属性,它甚至显示为PatientEntity类型,但是当此方法使用InvokeMember递归调用自身时(这是我试图使用属性Type调用它的方式)在第二次调用中,GetType(T)的类型为PersonEntity,它没有PatientType。有关如何正确解析嵌套调用中的类型的任何建议吗?
这个方法会像这样调用:
VisitEntity.IsValidSearchProperty("Patient.FirstName")
VisitEntity.IsValidSearchProperty("Patient.PatientType") '* This one doesn't work
PatientEntity.IsValidSearchProperty("PatientType")
PatientEntity.IsValidSearchProperty("FirstName")
更新
以下是关于我如何使用它的更多内容:
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类似于“Patient.PatientType True; Patient.FirstName True”
答案 0 :(得分:2)
我不知道为什么InvokeMember
会调用基类型而不是当前类型。但是,我会改变函数来解决这种行为。下面使用函数的私有重载,该类将类型作为参数进行检查。当函数向下钻取时,它可以调用此重载并将其传递给它想要检查的类型。这应该消除调用该方法的类的问题以及该类将返回的值GetType(T)
。
Public Shared Function IsValidSearchProperty(name As String) As Boolean
Dim CurrentType = GetType(T).GetProperties()
Return IsValidSearchProperty(name, CurrentType)
End Function
Private Shared Function IsValidSearchProperty(name As String, CurrentType as Type) 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() = CurrentType.GetProperties()
For Each prop As PropertyInfo In properties
If prop.Name = rootPart Then
If nested Then
'This is where my issue is'
Return IsValidSearchProperty(name.Substring(name.IndexOf(".") + 1), prop.PropertyType)
Else
Return True
End If
End If
Next
Return False
End Function
答案 1 :(得分:1)
我做了一些自己玩的事,想知道这可能是你的问题......
Sub Main
PersonEntity.IsValidSearchProperty()
PatientEntity.IsValidSearchProperty()
End Sub
' Define other methods and classes here
public class BaseEntity(of T)
public shared sub IsValidSearchProperty ()
Console.Write(GetType(T))
end sub
end class
public class PersonEntity
inherits BaseEntity(of PersonEntity)
end class
public class PatientEntity
inherits PersonEntity
end class
以下是我认为您的继承有效的一个简单示例。我假设构造BaseEntity时传递的泛型参数是有问题的实体。我假设PersonEntity是具体的而不是具有泛型参数的另一个抽象。
我列出的代码的问题是,对于PatientEntity,在调用IsValidSearchProperty
时类型参数T仍然是PersonEntity
继承自PersonEntity类。
这可能与您的班级相同或不同,但如果您的GetType返回PersonEntity而不是PatientEntity,那么这似乎是您的问题。
我假设如果您要对这些类的实例进行排序,那么您有一个实例并且可以将其转换为实例方法吗?
或者你也可以将类型显式地传递给递归函数,这样你就可以在泛型参数上使用getType,从属性的类型中得出类型并正确地传递它(毕竟你拥有属性)所以没有努力找到它的类。)
这个答案做了一些假设,但它们确实符合可观察的情况,所以我希望它们是正确和有帮助的。如果没有让我知道,我将编辑或删除。