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

如何访问多层嵌套非公开对象属性 解决反射与DirectCast调用异常

问题原因说明

  1. 反射获取m_Technology返回Nothing,90%以上的场景是因为没有指定正确的反射绑定标志,或者该私有字段定义在父类中,仅查询当前类型无法获取到字段定义
  2. HashtableDebugView是.NET内置的专供调试器使用的内部类,本身就不允许外部代码直接访问,你完全不需要使用这个类,直接操作m_ObjectToDataMap对应的Hashtable实例即可拿到目标元素

方案1:标准反射实现(兼容所有.NET版本,Option Strict 开启也可运行)

Imports System.Reflection
Imports System.Collections
Imports System.Dynamic

' 遍历获取类型的私有字段,支持从父类继承的私有字段
Function GetPrivateField(instance As Object, fieldName As String) As Object
    If instance Is Nothing Then Throw New ArgumentNullException(NameOf(instance))
    Dim currentType = instance.GetType()
    While currentType IsNot Nothing
        Dim field = currentType.GetField(fieldName, BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public)
        If field IsNot Nothing Then
            Return field.GetValue(instance)
        End If
        currentType = currentType.BaseType
    End While
    Throw New MissingFieldException($"未找到字段{fieldName}")
End Function

' 遍历获取类型的私有属性,支持从父类继承的私有属性
Function GetPrivateProperty(instance As Object, propName As String) As Object
    If instance Is Nothing Then Throw New ArgumentNullException(NameOf(instance))
    Dim currentType = instance.GetType()
    While currentType IsNot Nothing
        Dim prop = currentType.GetProperty(propName, BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public)
        If prop IsNot Nothing Then
            Return prop.GetValue(instance)
        End If
        currentType = currentType.BaseType
    End While
    Throw New MissingMemberException($"未找到属性{propName}")
End Function

' 主逻辑,遍历toollist中每个tool获取目标TypeName
For Each tool In toollist
    ' 1. 取m_Technology
    Dim mTechnology = GetPrivateField(tool, "m_Technology")
    ' 2. 取m_ObjectToDataMap
    Dim mObjectToDataMap = DirectCast(GetPrivateField(mTechnology, "m_ObjectToDataMap"), Hashtable)
    ' 3. 取Hashtable第一个元素的Value
    Dim firstEntryValue = mObjectToDataMap.Cast(Of DictionaryEntry)().First().Value
    ' 4. 取ComTypeDesc属性
    Dim comTypeDesc = GetPrivateProperty(firstEntryValue, "ComTypeDesc")
    ' 5. 取TypeName字段
    Dim typeName = DirectCast(GetPrivateField(comTypeDesc, "TypeName"), String)
    
    ' 这里拿到你要的typeName做后续处理
Next

方案2:后期绑定实现(代码更简洁,需要临时关闭Option Strict)

如果你的项目允许临时关闭严格类型检查,可以直接用后期绑定省略所有反射代码,运行时会自动查找非公开成员:

' 临时关闭严格类型检查,用完可以再开启
Option Strict Off
For Each tool In toollist
    Dim mTechnology = tool.m_Technology
    Dim dataMap = DirectCast(mTechnology.m_ObjectToDataMap, Hashtable)
    Dim firstValue = dataMap.Cast(Of DictionaryEntry)().First().Value
    Dim typeName = firstValue.ComTypeDesc.TypeName
    
    ' 这里拿到你要的typeName做后续处理
Next
Option Strict On

注意:如果你调试路径里写的ComTypeDes是正确拼写的,把上面代码里的ComTypeDesc改成你实际的成员名即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:06:04