如何访问多层嵌套非公开对象属性 解决反射与DirectCast调用异常
问题原因说明
- 反射获取
m_Technology返回Nothing,90%以上的场景是因为没有指定正确的反射绑定标志,或者该私有字段定义在父类中,仅查询当前类型无法获取到字段定义 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
相关产品推荐
相关产品推荐

