实现思路
- 使用
ExpandoObject
创建动态节点:ExpandoObject
允许在运行时动态添加属性,符合每个节点可动态添加属性的要求。
- 建立父子关系:在每个
ExpandoObject
中添加一个属性来存储子节点列表,以构建树状结构。
- 遍历树状结构:可以使用递归或迭代的方式遍历树,找到特定节点,并获取其所有动态属性。
核心代码片段
Imports System.Dynamic
' 创建树节点
Public Function CreateTreeNode() As ExpandoObject
Dim node As New ExpandoObject()
Dim childrenList As New List(Of ExpandoObject)()
CType(node, IDictionary(Of String, Object)).Add("Children", childrenList)
Return node
End Function
' 添加子节点
Public Sub AddChild(parent As ExpandoObject, child As ExpandoObject)
Dim children = CType(CType(parent, IDictionary(Of String, Object))("Children"), List(Of ExpandoObject))
children.Add(child)
End Sub
' 动态添加属性到节点
Public Sub AddDynamicProperty(node As ExpandoObject, propertyName As String, propertyValue As Object)
CType(node, IDictionary(Of String, Object)).Add(propertyName, propertyValue)
End Sub
' 递归遍历树并获取特定节点的所有动态属性
Public Function GetPropertiesOfNode(root As ExpandoObject, targetNode As ExpandoObject) As Dictionary(Of String, Object)
Dim result As New Dictionary(Of String, Object)()
If root Is targetNode Then
For Each kvp In CType(root, IDictionary(Of String, Object))
If kvp.Key <> "Children" Then
result.Add(kvp.Key, kvp.Value)
End If
Next
Return result
End If
Dim children = CType(CType(root, IDictionary(Of String, Object))("Children"), List(Of ExpandoObject))
For Each child In children
Dim childResult = GetPropertiesOfNode(child, targetNode)
If childResult.Count > 0 Then
Return childResult
End If
Next
Return result
End Function
示例使用
Module Module1
Sub Main()
' 创建根节点
Dim root = CreateTreeNode()
AddDynamicProperty(root, "Name", "RootNode")
' 创建子节点
Dim child1 = CreateTreeNode()
AddDynamicProperty(child1, "Name", "Child1")
AddChild(root, child1)
Dim child2 = CreateTreeNode()
AddDynamicProperty(child2, "Name", "Child2")
AddChild(root, child2)
' 获取Child1的所有动态属性
Dim properties = GetPropertiesOfNode(root, child1)
For Each kvp In properties
Console.WriteLine($"{kvp.Key}: {kvp.Value}")
Next
End Sub
End Module
遍历和获取特定节点属性说明
- 遍历:
GetPropertiesOfNode
方法采用递归方式遍历树。从根节点开始,如果当前节点是目标节点,则将其除“Children”之外的所有属性添加到结果字典中并返回。否则,递归地在子节点中查找目标节点。
- 获取属性:找到目标节点后,通过
IDictionary(Of String, Object)
接口遍历节点的属性,将非“Children”属性添加到结果字典,以此获取特定节点的所有动态属性。