2009-04-10 12 views
5

Estoy tratando de averiguar la mejor manera de ahorrar (serialización) y posteriormente abierta (deserializar) una estructura de árbol. Mi estructura está formada por varios tipos de objetos con diferentes propiedades, pero cada uno hereda de una clase abstracta "Nodo" básica.serialización/Derialization de una estructura de árbol

Cada nodo tiene ID único (GUID), y tiene una AddSuperNode (nd Node) método que va a establecer el padre de un nodo. Esto a su vez llama a otros métodos que permiten que el nodo padre sepa qué nodos secundarios tiene. Sin embargo, algunos nodos también utilizan un método AddAuxSuperNode() que agrega un elemento primario secundario al nodo.

que estaba usando la serialización binaria, pero ahora creo que quiero usar algo donde tengo un poco más de control, y los datos en serie es más accesible. También quiero conservar la información de tipo cuando deserializo, y ser capaz de serializar valores privados. Así que DataContractSerializer parecía la mejor manera de hacerlo.

No puedo simplemente serializar la raíz Nodo directamente porque los nodos tienen padres múltiples. No quiero crear objetos duplicados. Entonces parece que necesito deconstruir el árbol en una lista plana, y luego serializar eso. Luego, después de serializar esa lista, reconstruir el árbol. Suena bien?

Como dije antes cada Nodo tiene un identificador único de GUID, pero ahora los Nodos hacen referencia a sus padres/hijos directamente y no almacenan sus identificadores. Podría actualizar el AddSuperNode() y AddAuxSuperNode() métodos para actualizar también una lista de los identificadores de los padres a ser serializado además de las referencias directas. Pero prefiero solo actualizar/crear esta lista cuando el objeto se serializa. Así que estaba pensando en crear un método UpdateSuperNodeIDRefs() en el nodo que se llamaría justo antes de la serialización.

Lo siguiente es lo que estoy planeando hacer para la serialización y deserialización de esta estructura. ¿Puede alguien sugerir una forma mejor/más limpia/más eficiente para hacer esto?

serialización

1) Proporcionar el nodo raíz de la estructura de árbol

2) Divida estructura de árbol en un Diccionario plana (id Guid, nd Node) donde Identificación del es la guid de nd.

3) Llamada UpdateSuperNodeIDRefs(); para cada nodo para actualizar los ID que ha guardado para sus padres.

4) serializar el diccionario de nodos con DataContractSerializer

deserialización

1) deserializar el diccionario de nodos

2) Itterate a través de cada Nodo en el Diccionario, reconectando a cada uno con sus padres. Para los ID de los padres almacenados encontrar el respectivo Nodo (s) en el Diccionarioa juego con ID (s) llame a la AddSuperNode() o AddAuxSuperNode() a reconéctelo el nodo a su padre (s)

3) Desde cualquier nodo en el Diccionario encontrar la raíz de la estructura

4) Devuelve la raíz nodo

Respuesta

10

Si un nodo tiene padres múltiples, entonces no es un árbol; es, presumiblemente, un gráfico. Sin embargo, no te preocupes; DataContractSerializer puede manejar esto por usted:

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

    } 
} 
Cuestiones relacionadas