views:

218

answers:

3

I've got a working app that serializes a document (of type IDocument) to disk. From there there's another app that I've made that can open that document (IDocument implements IPrintDocument) for viewing.

Let's assume that I've written an IDocument to disk, and then a week later a field gets added to the IDocument object. Both the program that writes the files and the one that opens them are updated with this new 'version' of IDocument. It will then break (I assume - haven't had a chance to check, I'm looking ahead here) when trying to open the previous IDocument version. Is there a known pattern that alleviates this kind of problem?

+3  A: 

Yes - use a serialization mechanism which is tolerant to versioning.

Predictably enough, I'm going to suggest using Google's Protocol Buffers, for which there are at least two viable .NET implementations. So long as you're careful, Protocol Buffers are both backward and forward compatible - you can read a new message with old code and vice versa, and the old code will still be able to preserve the information it doesn't understand.

Another alternative is XML, whether using .NET's built-in XML serialization or not. The built-in serialization isn't particularly flexible in terms of versioning as far as I'm aware.

Jon Skeet
How is it possible that you know everything? Seriously. Consider this a career development question.
SnOrfus
In truth I know only a moderate amount, but I pimp my knowledge far and wide :) Seriously, you happen to have hit on my 20% project at work for this question. Some other questions I can answer off the top of my head - for other ones which interest me, I'll do a bit of research.
Jon Skeet
@Jon on the .net built-in serialization bit: as long as you define place holders for future extension you can also achieve backward/forward compatible.
eglasius
@Freddy: What kind of placeholders? Do you have to know the field names and types? 'Cos I don't have a crystal ball :)
Jon Skeet
@Jon sry, posted an answer with the info :)
eglasius
+1  A: 

Built in serialization should give you some minimal tolerance for version updates using the [OptionalField] attribute. But stuff can get tricky really fast so you better look at using a framework that solved these issues like Jons protobuffers etc...

Another couple of options would be to use an embedded DB like Sqlite for your document store. And manually (or using an ORM) map properties/fields in your object to columns in a table.

or

Use Lucene which will also give you fulltext search through your documents.

Sam Saffron
+2  A: 

The .net built-in serialization is an option, but it does requires you to add place holders on the specific pieces that you want to extend in the future.

You add place holders for the extra elements/attributes like the following code:

[XmlAnyElement()]
public XmlElement[] ExtendedElements { get; set; }
[XmlAnyAttribute()]
public XmlAttribute[] ExtendedAttributes { get; set; }

By adding the above in the involved classes, you can effectively read a information saved that has extra elements/attributes, modify the normal properties that the software knows how to handle and save it. This allows for both backwards and forward compatibility. When adding a new field, just add the desired property.

Note that the above is limited to extend in the specified hooks.

Update: As Jon mentioned in the comment, the above will only work for xml serialization. As far as I know binary serialization doesn't support something similar. In binary serialization you can get both old/new version of the app to be able to read each other serialized info (.net 2.0+), but if you save it back you will loose the extra info the version doesn't handles.

Starting at .net 2.0 the de-serialization process ignores the extra data, if you combine that with optional fields you can effectively get both apps to read other version's formats. The problem is that the data isn't hold by the class like in the xml fields.

Some related links: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.serializationbinder.aspx, http://msdn.microsoft.com/en-us/library/ms229752.aspx

If you don't want xml serialization, I would go with Jon's approach.

Ps. I am unaware if there is some good third party implementation, that we can access, that extends the binary serialization to hold and save the extra data.

eglasius
Clearly these attributes are only for XML serialization - is there anything similar for binary serialization?
Jon Skeet
Not that I am aware of, added an update about it.
eglasius