树结构的序列化/ Derialization

时间:2009-04-10 02:46:45

标签: c# serialization datacontractserializer datacontract

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

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

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

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

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

以下是我计划对此结构进行序列化和反序列化的操作。任何人都可以建议更好/更清洁/更有效的方法吗?

序列化

1)提供树结构的根节点

2)将树形结构细分为平面字典(Guid id,Node nd),其中 id guid ND

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

4)使用 DataContractSerializer

序列化词典节点

反序列化

1)反序列化节点的字典

2)浏览词典中的每个节点,将每个重新连接到其父级。对于存储的任何父ID,找到字典中相应的节点,并使用匹配的ID调用 AddSuperNode() AddAuxSuperNode()将节点重新连接到其父节点

3)从词典中的任何节点中找到结构的根

4)返回根节点

1 个答案:

答案 0 :(得分:10)

如果一个节点有多个父节点,那么它不是树;它可能是图形。但是 - 不用担心; 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));
        }

    }
}