【问题标题】:Serialization / Derialization of a tree structure树结构的序列化/反序列化
【发布时间】:2010-10-18 16:55:05
【问题描述】:

我正在尝试找出保存(序列化)然后打开(反序列化)树结构的最佳方法。我的结构由具有不同属性的各种对象类型组成,但每个对象类型都继承自一个基本的抽象“节点”类。

每个节点都有唯一的 ID (GUID),并且有一个 AddSuperNode(Node nd) 方法来设置节点的父节点。这反过来又调用了其他方法,允许父节点知道它有哪些子节点。但是,一些节点也使用 AddAuxSuperNode() 方法向节点添加辅助父节点。

我使用的是二进制序列化,但现在我想我想使用一些我有更多控制权的东西,并且序列化的数据更容易访问。我还想在反序列化时保留类型信息,并能够序列化私有值。所以 DataContractSerializer 似乎是最好的选择。

我不能直接序列化根 Node 因为节点有多个父节点。我不想创建重复的对象。所以看起来我需要将树解构为一个平面列表,然后将其序列化。然后在序列化该列表之后重建树。这听起来对吗?

就像我之前所说的,每个 节点 都有一个唯一的 GUID 标识符,但是现在节点直接引用它们的父/子而不存储它们的 id。除了直接引用之外,我还可以更新 AddSuperNode()AddAuxSuperNode() 方法来更新要序列化的父 ID 列表。但我宁愿只在对象被序列化时更新/创建这个列表。所以我想在节点中创建一个 UpdateSuperNodeIDRefs() 方法,该方法将在序列化之前被调用。

以下是我打算为这个结构的序列化和反序列化做的事情。谁能建议一种更好/更清洁/更有效的方法来做到这一点?

序列化

1) 提供树结构的根节点

2) 将树结构分解成一个扁平的Dictionary(Guid id,Node nd),其中idguid nd

3) 调用UpdateSuperNodeIDRefs();让每个节点更新它为其父节点保存的 ID。

4) 使用 DataContractSerializer

序列化节点的 Dictionary

反序列化

1) 反序列化节点的字典

2) 遍历 Dictionary 中的每个 Node,将每个节点重新连接到它们的父节点。对于存储的任何父 ID,在 Dictionary 中找到具有匹配 ID 的相应 Node,调用 AddSuperNode() >AddAuxSuperNode() 将节点重新连接到其父节点

3) 从字典中的任意节点中找到结构的根

4) 返回根节点

【问题讨论】:

    标签: c# serialization datacontractserializer datacontract


    【解决方案1】:

    如果一个节点有多个父节点,那么它就不是一棵树;它大概是一个图表。但是 - 不要担心; DataContractSerializer 可以为您处理:

    using System;
    using System.IO;
    using System.Runtime.Serialization;
    
    [DataContract]
    class Node {
        [DataMember]
        public Node AnotherNode { get; set; }
    }
    
    static class Program
    {
        static void Main()
        {
            Node a = new Node(), b = new Node();
            // make it a cyclic graph, to prove reference-mode
            a.AnotherNode = b;
            b.AnotherNode = a;
    
            // the preserveObjectReferences argument is the interesting one here...
            DataContractSerializer dcs = new DataContractSerializer(
                typeof(Node), null, int.MaxValue, false, true, null);
            using (MemoryStream ms = new MemoryStream())
            {
                dcs.WriteObject(ms, a);
                ms.Position = 0;
                Node c = (Node) dcs.ReadObject(ms);
                // so .AnotherNode.Another node should be back to "c"
                Console.WriteLine(ReferenceEquals(c, c.AnotherNode.AnotherNode));
            }
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-02
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-11
      相关资源
      最近更新 更多