2016-05-13 8 views
5

Ho implementato un metodo di clonazione in profondità utilizzando un costruttore di copie in C#. Per verificare che funzioni, lo sto testando confrontando i risultati della serializzazione di un oggetto e del suo clone. La serializzazione è fatta in termini di un oggetto generico T. Ho anche provato in termini di un oggetto concreto e ottenere gli stessi risultati.Serializzazione che modifica il contenuto dell'oggetto originale in C#

Ho un metodo per serializzare gli oggetti in array di byte

private byte[] ObjectToBytes(T obj) 
{ 
    BinaryFormatter formatter = new BinaryFormatter(); 
    using (MemoryStream stream = new MemoryStream()) 
    { 
     formatter.Serialize(stream, obj); 
     stream.Seek(0, SeekOrigin.Begin); 
     return stream.ToArray(); 
    } 
} 

Il seguente codice funziona bene.

T original = this.GetNewThing(); 
T clone = original.DeepClone(); 

// serialize after cloning 
byte[] originalBytes = ObjectToBytes(original); 
byte[] cloneBytes = ObjectToBytes(clone); 

bool equal = true; 
for (int i = 0; i < originalBytes.Length; i++) 
{ 
    if(originalBytes[i] != cloneBytes[i] 
    { 
     equal = false; 
     break; 
    } 
} 
equal == true; // True! 

Tuttavia, quando si passa all'ordine di quando gli oggetti sono serializzati, gli array di byte non sono più uguali.

// serialize before cloning 
T original = this.GetNewThing(); 
byte[] originalBytes = ObjectToBytes(original); 

T clone = original.DeepClone(); 
byte[] cloneBytes = ObjectToBytes(clone); 

bool equal = true; 
for (int i = 0; i < originalBytes.Length; i++) 
{ 
    if(originalBytes[i] != cloneBytes[i] 
    { 
     equal = false; 
     break; 
    } 
} 
equal == true; // False! 

Perché l'ordine di serializzazione influisce su questo? Ha qualcosa a che fare con gli oggetti BinaryFormatter o MemoryStream?

EDIT:

Ecco ciò che il metodo clone profonda sembra

public MyClass DeepClone() 
{ 
    return new MyClass(this); 
} 

e il costruttore utilizza assomiglia a questo

protected MyClass(MyClass myClass) 
{ 
    if (myClass == null) 
     throw new ArguementNullException("myclass"); 

    this.number = myClass.Number; 
    this.number2 = myClass.Number2; 
    this.number3 = myClass.Number3; 
} 

L'oggetto non è per nulla complesso mezzi. Tutti i valori copiati sono tipi di valori, quindi non ci sono tipi di riferimento che devono essere preoccupati.

+6

Si prega di inviare il metodo DeepClone .. Probabilmente c'è il problema –

+0

Potrebbe avere a che fare con la complessità degli oggetti - controlla questo: http://stackoverflow.com/questions/5017274/binaryformatter-and-deserialization-complex -oggetti – Clay

+0

Pensa che potremmo aver bisogno di vedere anche il pieno 'MyClass'. Inoltre, non ha stato, quindi perché 'ObjectToBytes' è un metodo di istanza privato e non statico? Penso che potrebbe essere utile se si potesse formattare un codice di esempio completo che potrebbe essere tagliato/incollato, per esempio, su LinqPad. –

risposta

4

DeepClone, o qualcosa che chiama a sua volta, sembra stia cambiando lo stato del vostro oggetto di origine.

+0

DeepClone cambia l'oggetto di origine accedendo a una proprietà che non è impostato fino al primo accesso. Quando clono prima di creare gli array di byte questo va bene, perché entrambe le proprietà vengono inizializzate durante il clone profondo. La creazione dell'array di byte prima della clonazione non causa l'inizializzazione di questa proprietà e la serializzazione non preleva i valori inizializzati (la proprietà è un tipo di valore, quindi preleva i valori predefiniti). – Danny

1

è necessario modificare il metodo ObjectToBytes come segue:

private byte[] ObjectToBytes(Object obj) 
    { 
     if(obj == null) 
      return null; 

     BinaryFormatter bf = new BinaryFormatter(); 
     using(MemoryStream ms = new MemoryStream()) { 
      bf.Serialize(ms, obj); 

      return ms.ToArray(); 
     } 
    } 

Speranza che aiuta

+0

Puoi spiegare come pensi che questo aiuti? – adv12

+0

@ adv12 perché è una cattiva pratica modificare la posizione del flusso prima di .Array. È una prova, ma mi piacerebbe vedere l'implementazione di DeepClone. – RobertoB

+0

Ho rimosso la chiamata non necessaria a "Cerca" nel mio codice. Non ha risolto il problema. Inoltre non ha causato alcun problema quando l'ho rimosso, quindi lo lascerò fuori. – Danny

Problemi correlati