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

如何持久化附带Machine对象的TreeView节点Tag属性?

解决方案:序列化Machine类以保留TreeView节点Tag的实际数据

是的,你必须对Machine类进行序列化处理,才能在XML持久化时保存它的IP、FQDN和友好名称等实际数据,之后程序启动反序列化TreeView时,再将重建的Machine对象绑定到对应节点的Tag属性上。以下是具体实现步骤:

1. 让Machine类支持序列化

给Machine类添加[Serializable]特性,并确保有无参构造函数(反序列化必须依赖无参构造函数重建对象):

[Serializable]
public class Machine
{
    public string MachineFQDN { get; set; }
    public string MachineName { get; set; }
    public string MachineIP { get; set; }

    // 反序列化必须的无参构造函数
    public Machine() { }

    public Machine(string fqdn, string name, string ip)
    {
        MachineFQDN = fqdn;
        MachineName = name;
        MachineIP = ip;
    }
}

2. 修改TreeViewSerializer的序列化逻辑

原来的代码直接调用node.Tag.ToString()只会保存类名,现在要判断Tag是否为Machine类型,将其属性序列化为XML子元素:

private void SaveNodes(TreeNodeCollection nodesCollection, XmlTextWriter textWriter)
{
    for (int i = 0; i < nodesCollection.Count; i++)
    {
        TreeNode node = nodesCollection[i];
        textWriter.WriteStartElement(XmlNodeTag);
        textWriter.WriteAttributeString(XmlNodeTextAtt, node.Text);
        textWriter.WriteAttributeString(XmlNodeImageIndexAtt, node.ImageIndex.ToString());

        if (node.Tag != null)
        {
            if (node.Tag is Machine machine)
            {
                // 将Machine的属性写入XML子节点
                textWriter.WriteStartElement("Machine");
                textWriter.WriteElementString("FQDN", machine.MachineFQDN);
                textWriter.WriteElementString("Name", machine.MachineName);
                textWriter.WriteElementString("IP", machine.MachineIP);
                textWriter.WriteEndElement();
            }
            else
            {
                // 兼容其他类型的Tag,保留原逻辑
                textWriter.WriteAttributeString(XmlNodeTagAtt, node.Tag.ToString());
            }
        }

        if (node.Nodes.Count > 0)
        {
            SaveNodes(node.Nodes, textWriter);
        }
        textWriter.WriteEndElement();
    }
}

3. 修改TreeViewSerializer的反序列化逻辑

读取XML时识别Machine子元素,重建Machine对象并赋值给节点的Tag:

public void DeserializeTreeView(TreeView tv, string filename)
{
    XmlTextReader reader = null;

    try
    {
        tv.BeginUpdate();
        reader = new XmlTextReader(filename);
        TreeNode parentNode = null;
        TreeNode currentNode = null;

        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element)
            {
                if (reader.Name == XmlNodeTag)
                {
                    TreeNode newNode = new TreeNode();
                    bool isEmptyElement = reader.IsEmptyElement;

                    // 加载节点基础属性
                    int attributeCount = reader.AttributeCount;
                    if (attributeCount > 0)
                    {
                        for (int i = 0; i < attributeCount; i++)
                        {
                            reader.MoveToAttribute(i);
                            SetAttributeValue(newNode, reader.Name, reader.Value);
                        }
                    }

                    // 添加节点到TreeView或父节点
                    if (parentNode != null)
                        parentNode.Nodes.Add(newNode);
                    else
                        tv.Nodes.Add(newNode);

                    currentNode = newNode;

                    if (!isEmptyElement)
                    {
                        parentNode = newNode;
                    }
                }
                else if (reader.Name == "Machine" && currentNode != null)
                {
                    // 读取Machine数据并创建对象
                    Machine machine = new Machine();
                    while (reader.Read() && reader.NodeType != XmlNodeType.EndElement)
                    {
                        if (reader.NodeType == XmlNodeType.Element)
                        {
                            switch (reader.Name)
                            {
                                case "FQDN":
                                    machine.MachineFQDN = reader.ReadElementContentAsString();
                                    break;
                                case "Name":
                                    machine.MachineName = reader.ReadElementContentAsString();
                                    break;
                                case "IP":
                                    machine.MachineIP = reader.ReadElementContentAsString();
                                    break;
                            }
                        }
                    }
                    currentNode.Tag = machine;
                }
            }
            else if (reader.NodeType == XmlNodeType.EndElement)
            {
                if (reader.Name == XmlNodeTag)
                {
                    parentNode = parentNode?.Parent;
                    currentNode = parentNode;
                }
            }
            // 保留原有其他节点类型的处理逻辑
            else if (reader.NodeType == XmlNodeType.XmlDeclaration)
            {
                // 忽略XML声明
            }
            else if (reader.NodeType == XmlNodeType.None)
            {
                return;
            }
            else if (reader.NodeType == XmlNodeType.Text)
            {
                if (parentNode != null)
                    parentNode.Nodes.Add(reader.Value);
            }
        }
    }
    finally
    {
        tv.EndUpdate();
        reader?.Close();
    }
}

为什么原来的代码无法保存实际数据?

你之前的代码调用node.Tag.ToString()时,默认返回的是Machine类的完全限定名(比如PRTG_Ripoff.Machine),并没有序列化对象的属性值。只有将对象的具体数据转换成XML可存储的结构,反序列化时才能重建完整的Machine对象并绑定到节点的Tag上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:15:41