2010-03-10 8 views
6

Durante el uso de este código para serializar un objeto:entero Objeto Clonar Gráfico

public object Clone() 
{ 
    var serializer = new DataContractSerializer(GetType()); 
    using (var ms = new System.IO.MemoryStream()) 
    { 
     serializer.WriteObject(ms, this); 
     ms.Position = 0; 
     return serializer.ReadObject(ms); 
    } 
} 

me he dado cuenta de que no copia las relaciones. ¿Hay alguna manera de que esto suceda?

+0

me di cuenta de la misma, puede llegar a algunos niveles, pero la mayoría terminas con un gráfico parcial e inútil. – leppie

+0

@leppie - se puede hacer, aunque ;-p –

Respuesta

16

basta con utilizar el sobrecarga de constructor que acepta preserveObjectReferences y la ponemos a true:

using System; 
using System.Runtime.Serialization; 

static class Program 
{ 
    public static T Clone<T>(T obj) where T : class 
    { 
     var serializer = new DataContractSerializer(typeof(T), null, int.MaxValue, false, true, null); 
     using (var ms = new System.IO.MemoryStream()) 
     { 
      serializer.WriteObject(ms, obj); 
      ms.Position = 0; 
      return (T)serializer.ReadObject(ms); 
     } 
    } 
    static void Main() 
    { 
     Foo foo = new Foo(); 
     Bar bar = new Bar(); 
     foo.Bar = bar; 
     bar.Foo = foo; // nice cyclic graph 

     Foo clone = Clone(foo); 
     Console.WriteLine(foo != clone); //true - new object 
     Console.WriteLine(clone.Bar.Foo == clone); // true; copied graph 

    } 
} 
[DataContract] 
class Foo 
{ 
    [DataMember] 
    public Bar Bar { get; set; } 
} 
[DataContract] 
class Bar 
{ 
    [DataMember] 
    public Foo Foo { get; set; } 
} 
+0

¡Duh! ¡Debería haber buscado más pistas! :) – leppie

+0

Esta debería ser la mejor manera que puedo ver ... gracias Marc, pero tengo un problema con Object.Object2.Object3, ¿esto puede ser un problema en el serializador? –

1

Anote sus clases con [DataContract] o agregue sus tipos secundarios en el constructor de DatacontractSerializer.

var knownTypes = new List<Type> {typeof(Class1), typeof(Class2), ..etc..}; 
var serializer = new DataContractSerializer(GetType(), knownTypes); 
+0

Gracias, esto parece funcionar también;) –

0

Se necesita un serializador binario para preservar la identidad objetos durante el paso de la serialización/deserialización.

+0

Sí, pero utilizo SqlMetal para crear las clases y la activación/serialización: Unidireccional. Disculpe las molestias. –

+0

No puedo entender cómo se relaciona su comentario con mi respuesta ...? Mire la muestra del código proporcionada por Darin Dimitrov – Seb

+1

Lo siento @Seb, pero eso no es correcto. DataContractSerializer * puede * copiar gráficos apropiados, y no es un serializador binario. Por el contrario, no es cierto que todos los serializadores binarios * puedan * necesariamente copiar gráficos. El soporte de gráficos y la salida binaria son conceptos ortogonales. –

1

Para realizar un clon de profundidad es posible considerar el uso de un serializador binario:

public static object CloneObject(object obj) 
{ 
    using (var memStream = new MemoryStream()) 
    { 
     var binaryFormatter = new BinaryFormatter(
      null, 
      new StreamingContext(StreamingContextStates.Clone)); 
     binaryFormatter.Serialize(memStream, obj); 
     memStream.Seek(0, SeekOrigin.Begin); 
     return binaryFormatter.Deserialize(memStream); 
    } 
}