3

在我的 ASP.Net MVC 页面中,我可以单击列标题以按该列排序,但这涉及 aspx 中的“魔术字符串”,这可能会导致运行时问题。我试图在运行时检查传递给排序依据的值是否有效。我有一个基类,我的所有实体都继承自:

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 最初是从查找 Patient 属性的 VisitEntity 调用的,它甚至显示为 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”

4

2 回答 2

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
于 2012-12-03T17:34:32.467 回答
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 (毕竟您拥有该属性,所以不费吹灰之力找到它的类)。

这个答案做了一些假设,但它们确实符合可观察的情况,所以我希望它们是正确的并有所帮助。如果不让我知道,我会编辑或删除。

于 2012-12-03T18:13:37.043 回答