1

Okay, I've asked some questions before on SO about serializing, but I'm still stuck - so I figure I'll just spit out my entire case instead of sub-problems in the hope someone can point my nose in the right direction :)

My application is similar to Apple's "Quartz Composer", which means I have a tree-like structure of connected nodes.

Nodes are defined by an INode interface; actual node-types/classes are imported from DLL's using MEF, so node-types will not be known at compile time.

Nodes are connected, so bidirectional links can and will occur.

I'd like to save my 'composition' - the entire tree of nodes - to a file, preferably human-readable like XML. I really want to avoid saving to a proprietary format !

So what I need to serialize is :

  • a tree of objects, whose classes can be runtime imported (and thus not known beforehand), which can contain bidirectional links.

  • On top of that I'd like to store version information for the used node classes, so it's possible to tell if a 'composition' was stored using an older version of some node class than the used dll / node class in the current application.

Previously I was pointed at the DataContractSerializer, which seems like a nifty tool to store my tree and fully support the bidirectional links.

But if I want to serialize my tree (Interface IComposition), it starts complaining about unknown types - I have to specify each specific type it can encounter while serializing the tree...

And also there's no way for me to specify which assembly-version was used for a specific node-class.

Somehow it doesn't feel right to first enumerate my entire tree to find out which node-classes have been used, add these to a known-types list, and then serialize.

And even then, I'd have to find a way to add a section to the output-data specifying version information for used classes.

Maybe I'm the only one with this problem, but I really hope someone else has encountered and conquered this problem before - preferably with an elegant solution ;) I can imagine it's not something that can be handled by a standard .NET serializer, but maybe there's some 3rd-party (free, open source even ?) implementation ?

Pygmy
  • 1,252
  • 17
  • 29

1 Answers1

0

You can accomplish this with BinaryFormatter or SoapFormatter. These formatters work with arbitrary object graphs, and will handle any objects they encounter (so long as the objects' types are marked [Serializable]) and will correctly preserve cyclic references. If you are curious to see how the objects are serialized, use SoapFormatter, which will output XML.

Note that any assemblies that could be loaded on demand will have to be in the GAC, or the runtime won't find them.

To deal with versioning, you could do something like this:

[Serializable]
public class SomeVersionedClass : IDeserializationCallback
{
    private const int CURRENT_VERSION = 10;

    private int version = CURRENT_VERSION;

    void IDeserializationCallback.OnDeserialization(object sender)
    {
        if (version != CURRENT_VERSION)
            throw new ApplicationException(
                "Mismatch between serialized data version " + version +
                " and required version " + CURRENT_VERSION + ".");
    }
}

Note that you might consider, instead of throwing an exception, migrating data from a previous version layout to the new version. Also, beware that removing serialized fields from a class will prevent future deserialization completely, so if you plan to allow migration away from a field that is no longer in use, you will have to leave that field in so that previous versions can deserialize properly (and, of course, so you can get at the data to migrate it).

cdhowie
  • 133,716
  • 21
  • 261
  • 264
  • Thanks for your answer, but can you by any chance point me to any page explaining more about how I'd implement my needs (bidirectional links, class versioning) using those ? My 5 minute Google kung-fu seems to weak... :) – Pygmy Dec 27 '10 at 22:02
  • Bidirectional and cyclic links will be handled transparently by the formatters; there is nothing you need to do to persist them. I will update my answer to provide a mechanism for dealing with versioning. – cdhowie Dec 27 '10 at 23:35