2010-08-23 12 views
6

Ho un C# classe che è serializzato su disco dal BinaryFormatter, come ad esempio questo esempio:Come rifattorizziamo una classe che è serializzato nel .NET?

// Version 3.0 
[Serializable] 
public class Person 
{ 
    public string FullName; 

    [OptionalField(VersionAdded=2)] 
    public string NickName; 
    [OptionalField(VersionAdded=2)] 
    public DateTime BirthDate; 

    [OptionalField(VersionAdded=3)] 
    public int Weight; 
} 

Più tardi, voglio refactoring questa classe da uno o più dei seguenti
- cambiare il suo nome
- Cambiare il suo spazio dei nomi
- Spostarsi in un'altra assemblea

per quanto posso dire, il file binario può essere de-serializzato solo se una classe con lo stesso nome, spazio dei nomi e il montaggio nome è disponibile.

Come posso aggirare questo?
E 'possibile mappare la de-serializzazione a un diverso nome di classe, spazio dei nomi e il montaggio senza rompere Version Tolerant Serialization?

risposta

5

Dopo alcune ricerche ho capito che il BinaryFormatter supporta tutto quello che cercavo.

Un BinaryFormatter può utilizzare surrogati a

  1. offre la possibilità di serializzare un tipo che non è stato originariamente progettato per essere serializzato.
  2. Fornisce un modo per mappare una versione di un tipo ad un altro la versione di un altro tipo.

Uno può anche mappare deserializzazione da tipo A a tipo B (diverso nome della classe, dello spazio dei nomi e/o il nome di montaggio) utilizzando SerializationBinder.

Per quanto posso dire, questo rende possibile il refactoring di classi serializzate e di mantenere la retrocompatibilità quando si effettuano modifiche di interruzione non supportate dalla sola versione.

Riferimento: http://www.diranieh.com/NETSerialization/BinarySerialization.htm

Edit: Una nota a parte, i campi di refactoring (nome o il tipo) è ancora un dolore, come discusso in Renaming fields then deserializing in C#. Attualmente sto cercando in protobuf-net per risolvere meglio questo in futuro.

1

È possibile implementare l'interfaccia ISerializable e sovrascrivere GetObjectData per fornire il proprio deserializzazione. Non ho provato, ma dovresti riuscire a deserializzare il tuo vecchio oggetto "manualmente".

+0

Quindi vuol dire persona dovrebbe attuare ISerializable e GetObjectData()? Come sarà il de-serializzatore sapere che questa classe esatto persona dovrebbe essere utilizzato, quando ha un nome diverso, dello spazio dei nomi e/o montaggio? Posso in qualche modo dire al de-serializer quale classe usare? – angularsen