如何在派生类上动态调用静态方法

时间:2012-11-30 16:03:08

标签: .net vb.net reflection static-methods invokemember

在我的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”

2 个答案:

答案 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,从属性的类型中得出类型并正确地传递它(毕竟你拥有属性)所以没有努力找到它的类。)

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

相关问题