You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过反射从父类访问子类的非公开属性?

VB.NET父类通过反射访问子类非Public属性失败的问题

我编写了两个存在继承关系的测试类,实际代码基于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 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属性不会抛出错误。请问我是否忽略了什么关键点?


核心原因:反射的默认绑定规则与访问权限检查

  • GetProperty的默认行为:调用[GetType].GetProperty("属性名")时,默认仅返回Public属性成员。Protected、Friend、ProtectedFriend这类非Public成员,必须显式指定绑定标志才能被检索到。
  • 运行时权限检查:即便通过绑定标志拿到非Public属性的PropertyInfo,调用GetValue时仍会触发.NET的访问权限校验:
    • Protected属性:父类可直接访问子类的Protected成员,但反射默认不绕过权限,需指定BindingFlags.NonPublic + BindingFlags.Instance。
    • Friend属性:Friend成员的访问范围仅限同一程序集内的所有类型,但反射默认不获取该类成员,必须指定BindingFlags.Instance + BindingFlags.NonPublic(Friend属于NonPublic范畴)。
    • ProtectedFriend属性:结合Protected与Friend的访问范围,同样需要指定正确的绑定标志才能通过反射获取。

修正后的代码示例

修改父类的Run方法,显式指定绑定标志并处理权限检查:

Public MustInherit Class ParentClass
  Public Sub Run()
    ' 定义绑定标志:包含实例的Public和非Public成员
    Dim bindingFlags = Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.NonPublic
    
    ' 访问Protected属性
    Dim protectedProp = [GetType].GetProperty("ProtectedProperty", bindingFlags)
    If protectedProp IsNot Nothing Then
        Console.WriteLine(protectedProp.GetValue(Me).ToString())
    End If
    
    ' 访问ProtectedFriend属性
    Dim protectedFriendProp = [GetType].GetProperty("ProtectedFriendProperty", bindingFlags)
    If protectedFriendProp IsNot Nothing Then
        Console.WriteLine(protectedFriendProp.GetValue(Me).ToString())
    End If
    
    ' 访问Friend属性
    Dim friendProp = [GetType].GetProperty("FriendProperty", bindingFlags)
    If friendProp IsNot Nothing Then
        Console.WriteLine(friendProp.GetValue(Me).ToString())
    End If
    
    ' 访问Public属性
    Dim publicProp = [GetType].GetProperty("PublicProperty")
    If publicProp IsNot Nothing Then
        Console.WriteLine(publicProp.GetValue(Me).ToString())
    End If
  End Sub
End Class

额外注意事项

  • 若父类与子类不在同一程序集,即使是Friend属性,父类也无法通过反射访问(Friend权限仅限同一程序集)。
  • 如需绕过严格权限检查,可使用PropertyInfo.GetValue的重载或配合BindingFlags调用,但需谨慎操作,避免破坏封装性。
  • 针对DLL场景,若要隐藏属性,除使用Friend/Protected修饰外,还可添加[EditorBrowsable(EditorBrowsableState.Never)]特性,防止属性在IntelliSense中显示,但不影响反射访问。

内容的提问来源于stack exchange,提问作者Josh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 18:50:20