views:

180

answers:

4

I have data that has been stored using binary serialization for the following class:

[Serializable]
public abstract class BaseBusinessObject
{
    private NameValueCollection _fieldErrors = new NameValueCollection();

    protected virtual NameValueCollection FieldErrors
    {
     get { return _fieldErrors; }
     set { _fieldErrors = value; }
    }

    ...
}

At some point, the class was changed to this:

[Serializable]
public abstract class BaseBusinessObject
{
    private Dictionary<string, string> _fieldErrors = new Dictionary<string, string>();

    protected virtual Dictionary<string, string> FieldErrors
    {
     get { return _fieldErrors; }
     set { _fieldErrors = value; }
    }

    ...
}

This is causing issues deserializing old data.

My first thought was to implement ISerializable, but this class has numerous properties as well as hundreds of inheriting classes that I would have to implement this for as well.

I would like to either change the old data to match the current structure during deserialization or have a clean way of upgrading the old data.

+2  A: 

If the data is only used internally, my first thought would be to write some simple throw-away code to de-serialize your binary data using the old "NameValueCollection", map it to a Dictionnary and re-serialize it. Even if it'll take a few days to process all the data, it doesn't seem worth it to implement a patch on your new code to support the old data.

Even if it's not only used internally, an importer seems like the simplest way to go.

OlivierD
+1  A: 

Adding to OlivierD's good advice, I'd suggest you define both classes but initially try to deserialize as the current version. In your catch block, deserialize it as the legacy version, then upgrade it to the current one and save it back. When no instances of the legacy version exist, you can remove the code.

Steven Sudit
+2  A: 

Add the new _fieldErrors under a different name, say _fieldErrors2, and make it [Optional]. Then implement an [OnDeserialized] Method that copies the data from _fieldErrors to _fieldErrors2 (if present), and clears _fieldErrors.

Martin v. Löwis
This provided the most realistic approach for my needs, but I ended up going down a different route.
Aethyrial
A: 

After investigating a few options, I made the following conclusions:

Ideally I would be able to access the value from the original NameValueCollection and manually convert it to Dictionary<string, string>. The only way to do this would be to implement ISerializable, but this posed two major issues: matching up to the naming of the legacy data and the inclusion of serialization logic for all inheriting classes (of which there are hundreds).

Effectively, this put me in a bind. Fortunately, I was able to determine that this field is really only used as a summary of form validation errors and shouldn't be getting serialized in the first place, therefore I have excluded it from serialization.

Aethyrial