It sounds strange but this is exactly what I want because I am using a data structure named “Project” which gets serialized to a save file. I would like to be able to de-serialize an older version of a save file with deprecated fields in tact, but then re-serialize it using only the currently used fields. The problem is that I want to get rid of those deprecated fields when re-serializing the structure in order to minimize file size. Is it possible to mark a field as “de-serializable only”?
Edit:
Thanks for the ideas! I decided to build mostly off of NickLarsen’s suggestions and create an old version of the project structure with all depreciated fields in a separate namespace. The difference is that I decided to perform the upgrade upon deserialization. This is great because I can do it all in one line (hopefully you can get the gist what I’m doing here):
Project myProject = new Project((Depreciated.Project)myFormatter.Deserialize(myStream));
The constructor simply returns a new instance of the fresh minimal data structure based on the old bloated one.
Second Edit:
I decided to follow the advice of bebop instead and create new classes for each project version with the oldest version including all depreciated and new fields. Then the constructor of each project upgrades to the next version getting rid of depreciated fields along the way. Here is an illustrative example of converting from version 1.0.0 -> 1.0.5 -> current.
Project myProject = new Project(new Project105((Project100)myFormatter.Deserialize(myStream)));
One key to this is to forced the deserialized file as well as any fields into the older versions of the classes by using a SerializationBinder.
could you not create a new version of your data structure class each time the structure changes, and have the constructor for the new class take an instance of the previous class, and populate itself from there. To load the newest class you try and create the earliest class from the serialised file until one succeeds, and then pass that into the constructor of the next class in the chain repeatedly until you get the latest version of the data structure then you can save that.
Having a new class for each change in format would avoid having to change any existing code when the data structure changed, and your app could be ignorant of the fact that the save file was some older version. It would allow you to load from any previous version, not just the last one.
This sort of thing implemented by a chain of responsibility can make it easy to slot in a new format with minimal changes to your existing code.
Whilst not a textbook chain of responsibility you could implement with something like this:
(NOTE: untested code)
this has the advantage that when you want to add ProductV3 you only need to change the class you are using in your app to be a ProductV3 type, which you need to do anyway, then you change your loading code so that it uses a ProductV3Factory, which is basically the same as a ProductV2Factory, but it uses a ProductV2Factory as the successor. You don’t need to change any existing classes. you could probably refactor this a bit to get the commanality of
CreateProductinto a base class, but it gets the idea across.