树结构的序列化/ Derialization

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

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

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

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

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

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

序列化

1)提供树结构的根节点

2)将树结构分解为平面词典(Guid id,Node nd) ,其中idndguid

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

4)使用DataContractSerializer序列化节点字典

反序列化

1)反序列化节点字典

2)遍历字典中的每个节点 ,将每个节点重新连接到其父节点 。 对于存储的任何父ID,查找具有匹配ID的字典中的相应节点调用AddSuperNode()AddAuxSuperNode()以将节点重新连接到其父节点。

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

4)返回根节点

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