5

ツリー構造を保存(シリアル化)して後で開く(逆シリアル化)ための最良の方法を見つけようとしています。私の構造は、さまざまなプロパティを持つさまざまなオブジェクトタイプで構成されていますが、それぞれが基本抽象「Node」クラスを継承しています。

各ノードには一意のID(GUID)があり、ノードの親を設定するAddSuperNode(Node nd)メソッドがあります。これにより、親ノードがどのサブノードを持っているかを知ることができる他のメソッドが呼び出されます。ただし、一部のノードは、ノードにセカンダリ親を追加するAddAuxSuperNode()メソッドも利用します。

バイナリシリアル化を使用していましたが、今はもう少し制御しやすく、シリアル化されたデータにアクセスしやすいものを使用したいと思います。また、逆シリアル化するときにタイプ情報を保持し、プライベート値をシリアル化できるようにしたいです。したがって、 DataContractSerializerは最善の方法のように思われました。

ノードに複数の親があるため、ルートノードを直接シリアル化することはできません。重複するオブジェクトを作成したくありません。したがって、ツリーをフラットリストに分解してから、シリアル化する必要があるように思われます。次に、そのリストをシリアル化した後、ツリーを再構築します。これは正しいですか?

前に述べたように、各ノードには一意のGUID識別子がありますが、現在、ノードは親/子を直接参照しており、IDを保存していません。AddSuperNode ()メソッドとAddAuxSuperNode()メソッドを更新して、直接参照に加えて、シリアル化する親IDのリストも更新できます。ただし、オブジェクトがシリアル化されているときにのみ、このリストを更新/作成したいと思います。そのため、シリアル化の直前に呼び出されるノードにUpdateSuperNodeIDRefs()メソッドを作成することを考えていました。

以下は、この構造のシリアル化と逆シリアル化のために私が計画していることです。誰かがこれを行うためのより良い/よりクリーンな/より効率的な方法を提案できますか?

シリアル化

1)ツリー構造のルートノードを提供します

2)ツリー構造をフラットな辞書(Guid id、Node nd)に分解します。ここで、idndのGUIDです。

3)UpdateSuperNodeIDRefs( )を呼び出します; 各ノードがその親のために保存したIDを更新します。

4)DataContractSerializerを使用してノードのディクショナリをシリアル化します

デシリアライズ

1)ノードのディクショナリを逆シリアル化します

2)ディクショナリ内の各ノード繰り返し処理し、それぞれを親に再接続します。保存されている親IDについては、一致するIDを持つ辞書でそれぞれのノードを見つけ、AddSuperNode ()またはAddAuxSuperNode()を呼び出してノードそのに再接続します。

3)ディクショナリ内の任意のノードから、構造のルートを見つけます

4)ルートノードを返す

4

1 に答える 1

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));
        }

    }
}
于 2009-04-10T07:48:45.747 に答える