views:

372

answers:

4

I have data stored in an instance of a class which has been serialized with the .net BinaryFormatter. I now want to rename one of the fields in the class, but still be able to deserialize the old data.

One option is to implement ISerializable and deserialize all the the fields of the class manually. But this seems like a lot of work, especially if my class has lots of fields and I've only renamed a single field.

Is there a better way?


Craig suggests keeping a copy of the old class for deserialization, and copying values to the new class. I've seen this suggested elsewhere too - what advantage does this have over implementing ISerializable? As far as I can see, copying the class leaves me with 2 almost identical copies of the class plus I still have to copy all the values from the old class to the new class - which seems the same amount of work as implementing ISerializable with an almost duplicate class thrown into mix.


Two answers have mentioned Binders. I've successfully used a SerializationBinder to deserialize a class Bar which was Serialized as class Foo, but that's because the name of the class changed. Does SerializationBinder also help when you've renamed a field - say when int m_Left has been renamed to int m_Right?

+1  A: 

You could try having the old calss hang around for the sole purpose of rehydration and then just copy over the fields you need to the new class. Still kind of painful but should work.

Craig
+1  A: 

Yes, this is the problem with field-based serializers. You can use either a custom Binder, or a "serialization surrogate" to avoid implementing ISerializable, but that is only a case-by-case fix.

I've discussed this topic (in the context of obfuscators, and auto-props) here. My advice is: don't use BinaryFormatter for persistance of data between versions... for that, look at contract-based serializers:

  • XmlSerializer
  • DataContractSerializer
  • or for binary, things like protobuf-net

None of this helps you today, but it might help you design around it in the future.

Marc Gravell
A: 

I used SerializationBinder class for this before

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.serializationbinder.aspx

it can be used for deserialization so you can remap old type to new one.

Andrija
A: 

What if you just change the access modifier on that one property to private, and then have a public property with the new name that just basically wraps the old one. That way you should still be able to deserialize (I THINK) but anyone using this class won't know about the old name. Just a thought...

BFree
That would work if the serialization was acting on properties, but as far as I can tell, it's working directly with the private fields anyway... (if I open the file in notepad, I see field names like m_Foo and m_Bar, instead of property names like Foo and Bar...
Tim Gradwell