How to refactor a class that is serialized in .NET?
Asked Answered
B

2

7

I have a C# class that is serialized to disk by the BinaryFormatter, such as this example:

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

Later, I want to refactor this class by one or more of the following
- Change its name
- Change its namespace
- Move to another assembly

As far as I can tell, the binary file can only be de-serialized if a class with the exact same name, namespace and assembly name is available.

How do I work around this?
Is it possible to map the de-serialization to a different class name, namespace and assembly without breaking Version Tolerant Serialization?

Baccalaureate answered 23/8, 2010 at 7:37 Comment(0)
B
5

After some research I realized that the BinaryFormatter does support everything I was looking for.

A BinaryFormatter can use surrogates to

  1. Provides the ability to serialize a type that was not originally designed to be serialized.
  2. Provides a way to map one version of a type to another version of another type.

One can also map deserialization from type A to type B (different class name, namespace and/or assembly name) by using SerializationBinder.

As far as I can tell, this makes it possible to refactor classes that are serialized and to maintain backwards compatibility when making breaking changes that is not supported by versioning alone.

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

Edit: On a side note, refactoring fields (name or type) is still a pain, as discussed in Renaming fields then deserializing in C#. I am currently looking into protobuf-net to better solve this in the future.

Baccalaureate answered 28/9, 2010 at 7:7 Comment(0)
V
1

You can implement the ISerializable interface and override GetObjectData to provide your own deserialization. I have not tried, but you should be able to deserialize your old object "manually".

Vasilikivasilis answered 23/8, 2010 at 7:46 Comment(1)
So you mean Person should implement ISerializable and GetObjectData()? How will the de-serializer know that this exact Person class should be used, when it has a different name, namespace and/or assembly? Can I somehow tell the de-serializer which class to use?Baccalaureate

© 2022 - 2024 — McMap. All rights reserved.