C# 如何使用反射从多级继承类获取受保护的好友属性?

C# 如何使用反射从多级继承类获取受保护的好友属性?,c#,vb.net,reflection,properties,C#,Vb.net,Reflection,Properties,我的班级结构有点像这样 public class a Protected Friend Property ID() As Integer Get Return _Id End Get Set(ByVal Value As Integer) _Id = Value End Set End Property //some other properties

我的班级结构有点像这样

 public class a
       Protected Friend Property ID() As Integer
        Get
            Return _Id
        End Get
        Set(ByVal Value As Integer)
            _Id = Value
        End Set
    End Property 
    //some other properties and methods
 End class


 public class b 
       Inherits a
        //some properties and methods
 End Class


 public class c 
       Inherits b
        //some properties and methods
 End Class

 public class d 
       Inherits c
        //some properties and methods

       Dim obj as D = new D();
       Dim data = obj.GetType().GetProperties(/*I have tried all binding flags here*/) 

 End Class
我想从
class D
的对象访问
class a
中的
ID
属性。到目前为止,我在谷歌上搜索并从堆栈中找到了很多答案,但这些答案中的任何一个都没有给出我想要的

当我使用这样的代码时,我得到了这个属性

 'obj.GetType().BaseType.BaseType.BaseType.GetProperties()'
但是重复的
BaseType
属性的使用看起来不太好,而且如果我将来在这两者之间添加更多的继承,也可能会导致问题。那么有没有办法避免这种情况并得到我想要的呢。如果有任何困惑,请随时发表评论


另外,我已经尝试了很多关于这个问题的答案,但是没有得到我想要的。如果你知道C#方式,那么也请建议我将其转换为VB

您可以直接访问您的财产

  Module Module1

        Sub Main()
            Dim test As d = New d()
            test.EntityID = 52
            Dim t As Integer = test.EntityID
            Dim t1 As Integer = test.GetEntityID

        End Sub


        Public Class a
            Dim _entityId As Integer
            Protected Friend Property EntityID() As Integer
                Get
                    Return _entityId
                End Get
                Set(ByVal Value As Integer)
                    _entityId = Value
                End Set
            End Property

        End Class


        Public Class b
            Inherits a

        End Class


        Public Class c
            Inherits b

        End Class

        Public Class d
            Inherits c


            Public Function GetEntityID() As Integer

                Dim test As Integer = Me.EntityID
                Return test
            End Function

        End Class

    End Module

您可以直接访问您的财产

  Module Module1

        Sub Main()
            Dim test As d = New d()
            test.EntityID = 52
            Dim t As Integer = test.EntityID
            Dim t1 As Integer = test.GetEntityID

        End Sub


        Public Class a
            Dim _entityId As Integer
            Protected Friend Property EntityID() As Integer
                Get
                    Return _entityId
                End Get
                Set(ByVal Value As Integer)
                    _entityId = Value
                End Set
            End Property

        End Class


        Public Class b
            Inherits a

        End Class


        Public Class c
            Inherits b

        End Class

        Public Class d
            Inherits c


            Public Function GetEntityID() As Integer

                Dim test As Integer = Me.EntityID
                Return test
            End Function

        End Class

    End Module

我在
d
中创建了一个子
Sub

Sub DoStuff()
    Dim obj As d = New d()
    Dim data = obj.GetType().GetProperties(BindingFlags.Instance Or BindingFlags.NonPublic)
End Sub
当我跨过
data
行时,
data
被设置为一个数组,该数组包含一个属性,即
a
类中的
EntityID
属性

或者,如果不想搜索该数组,可以直接转到该属性:

Dim eid = obj.GetType().GetProperty("EntityID", _
                                    BindingFlags.Instance Or BindingFlags.NonPublic)

我在
d
中创建了一个子
Sub

Sub DoStuff()
    Dim obj As d = New d()
    Dim data = obj.GetType().GetProperties(BindingFlags.Instance Or BindingFlags.NonPublic)
End Sub
当我跨过
data
行时,
data
被设置为一个数组,该数组包含一个属性,即
a
类中的
EntityID
属性

或者,如果不想搜索该数组,可以直接转到该属性:

Dim eid = obj.GetType().GetProperty("EntityID", _
                                    BindingFlags.Instance Or BindingFlags.NonPublic)

您尚未尝试所有绑定标志

myD.GetType().GetProperties(
              BindingFlags.NonPublic or _
              BindingFlags.Instance)
应该有用。我做了一把小提琴:

或直接:

myD.GetType().GetProperty("EntityID", 
              BindingFlags.NonPublic or _
              BindingFlags.Instance)

更新:正如@Damien\u异教徒指出的那样,
flatthierarchy
对于实例属性是不必要的

您还没有尝试所有绑定标志

myD.GetType().GetProperties(
              BindingFlags.NonPublic or _
              BindingFlags.Instance)
应该有用。我做了一把小提琴:

或直接:

myD.GetType().GetProperty("EntityID", 
              BindingFlags.NonPublic or _
              BindingFlags.Instance)

更新:正如@Damien\u异教徒指出的那样,
扁平化层次结构
对于实例属性来说是不必要的

谢谢你的想法

我尝试添加GetPropertyName()

很好

        Sub DoStuff()
            Dim obj As d = New d()
            Dim data As PropertyInfo = obj.GetType().GetProperty(GetPropertyName(Function() obj.EntityID), BindingFlags.Instance Or BindingFlags.NonPublic)
            Dim x = data.GetValue(obj, Nothing)
        End Sub
        Public Function GetPropertyName(Of T)(prop As Expression(Of Func(Of T))) As String
            Dim expression = GetMemberInfo(prop)
            Return expression.Member.Name
        End Function
        Private Function GetMemberInfo(method As Expression) As MemberExpression
            Dim lambda As LambdaExpression = TryCast(method, LambdaExpression)
            If lambda Is Nothing Then
                Throw New ArgumentNullException("method")
            End If

            Dim memberExpr As MemberExpression = Nothing

            If lambda.Body.NodeType = ExpressionType.Convert Then
                memberExpr = TryCast(DirectCast(lambda.Body, UnaryExpression).Operand, MemberExpression)
            ElseIf lambda.Body.NodeType = ExpressionType.MemberAccess Then
                memberExpr = TryCast(lambda.Body, MemberExpression)
            End If

            If memberExpr Is Nothing Then
                Throw New ArgumentException("method")
            End If

            Return memberExpr
        End Function
谢谢你的想法

我尝试添加GetPropertyName()

很好

        Sub DoStuff()
            Dim obj As d = New d()
            Dim data As PropertyInfo = obj.GetType().GetProperty(GetPropertyName(Function() obj.EntityID), BindingFlags.Instance Or BindingFlags.NonPublic)
            Dim x = data.GetValue(obj, Nothing)
        End Sub
        Public Function GetPropertyName(Of T)(prop As Expression(Of Func(Of T))) As String
            Dim expression = GetMemberInfo(prop)
            Return expression.Member.Name
        End Function
        Private Function GetMemberInfo(method As Expression) As MemberExpression
            Dim lambda As LambdaExpression = TryCast(method, LambdaExpression)
            If lambda Is Nothing Then
                Throw New ArgumentNullException("method")
            End If

            Dim memberExpr As MemberExpression = Nothing

            If lambda.Body.NodeType = ExpressionType.Convert Then
                memberExpr = TryCast(DirectCast(lambda.Body, UnaryExpression).Operand, MemberExpression)
            ElseIf lambda.Body.NodeType = ExpressionType.MemberAccess Then
                memberExpr = TryCast(lambda.Body, MemberExpression)
            End If

            If memberExpr Is Nothing Then
                Throw New ArgumentException("method")
            End If

            Return memberExpr
        End Function

请说明原因?您可以直接访问d类中的EntityID属性。或者我不明白你的问题。您可以在方法或属性中访问EntityID,这是示例代码中C#和VB的混淆组合(例如,它看起来像VB,但有C#风格的注释和零散的
(另外,“如果底部的代码在有效块内,例如
函数
,则效果更好”)@Damien#u不信教者很抱歉,基本上我是c#coder最近开始使用VB,所以在这里输入时出现了旧习惯。很抱歉。请说明原因?您可以直接访问d类中的EntityID属性。或者我不理解您的问题。您可以通过方法或属性访问EntityID示例代码中C#和VB的混淆组合(例如,它看起来像VB,但有C#风格的注释和零散的
(另外,“如果底部的代码在有效块内,例如
函数
,则效果更好”)@Damien#u The#u The#u unsivers抱歉,基本上我是c#coder最近开始使用VB,所以在这里输入时出现了旧习惯。抱歉。因为问题被标记,标题以“使用反射”结尾,我想他们在这里寻找基于反射的答案。抱歉,现在我明白了,因为问题被标记,标题以“使用反射”结尾,我想他们在这里寻找基于反射的答案。抱歉,现在我明白了这里不需要
flatthierarchy
。它只与静态相关(或者用VB的说法是
Shared
)@Damien\u不相信你是完全正确的,而且,现在我读到了,你的答案已经是正确的。让我更新并更新你的答案
Shared
在这里不是必需的。它只与静态相关(或者用VB的说法是
Shared
)@Damien_,不相信你的人,你是完全正确的,而且,现在我读了,你的答案已经是正确的。让我更新并更新你的答案