代码之家  ›  专栏  ›  技术社区  ›  Josh

通过反思访问孩子的财产

  •  1
  • Josh  · 技术社区  · 1 年前

    我有这两个类作为测试,一个继承了另一个。测试所基于的真实代码是一个DLL,所以我不想将每个属性都暴露给DLL的用户。我希望能够通过反射从父母那里访问孩子的属性。

    Public Module App
      Public Sub Main()
        Dim child As New ChildClass()
        child.Run()
      End Sub
    End Module
    
    Public MustInherit Class ParentClass
      Public Sub Run()
        [GetType].GetProperty("ProtectedProperty").GetValue(Me).ToString() 'Error
        [GetType].GetProperty("ProtectedFriendProperty").GetValue(Me).ToString() 'Error
        [GetType].GetProperty("FriendProperty").GetValue(Me).ToString() 'Error
        [GetType].GetProperty("PublicProperty").GetValue(Me).ToString() 'Success
        End
      End Sub
    End Class
    
    Public Class ChildClass
      Inherits ParentClass
      Protected Property ProtectedProperty As String = "Protected"
      Protected Friend Property ProtectedFriendProperty As String = "ProtectedFriend"
      Friend Property FriendProperty As String = "Friend"
      Public Property PublicProperty As String = "Public"
    End Class
    

    我本以为任何Friend属性都可以从父级访问,但只有Public属性不会抛出错误。我错过了什么吗?

    1 回复  |  直到 1 年前
        1
  •  5
  •   Stina Andersson    1 年前

    在您的代码中,问题是因为GetProroperty的默认行为只考虑公共属性。

    要访问非公共属性,如Protected、Protected Friend或Friend,您需要指定适当的 BindingFlags .

    这样地:

    Public MustInherit Class ParentClass
        Public Sub Run()
            Dim bindingFlags As BindingFlags = BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public
    
            Dim protectedProp = Me.GetType().GetProperty("ProtectedProperty", bindingFlags)
            If protectedProp IsNot Nothing Then
                Console.WriteLine(protectedProp.GetValue(Me).ToString())
            End If
    
            Dim protectedFriendProp = Me.GetType().GetProperty("ProtectedFriendProperty", bindingFlags)
            If protectedFriendProp IsNot Nothing Then
                Console.WriteLine(protectedFriendProp.GetValue(Me).ToString())
            End If
    
            Dim friendProp = Me.GetType().GetProperty("FriendProperty", bindingFlags)
            If friendProp IsNot Nothing Then
                Console.WriteLine(friendProp.GetValue(Me).ToString())
            End If
    
            Dim publicProp = Me.GetType().GetProperty("PublicProperty", bindingFlags)
            If publicProp IsNot Nothing Then
                Console.WriteLine(publicProp.GetValue(Me).ToString())
            End If
        End Sub
    End Class
    

    添加正确的绑定标志应该能解决这个问题。

    请注意,Protected属性是可访问的,因为它是由父类继承的,并且 BindingFlags.NonPublic 在搜索中包括受保护的成员。

    朋友和受保护的朋友属性是可访问的,因为 绑定标志。非公开 只要它们在同一组件内,就允许访问它们。

    这种方式应该使您的ParentClass能够使用反射访问ChildClass的所有属性,而不管它们的访问级别如何。