Promit's Ventspace

February 20, 2010

How to Serialize Interfaces in .NET

Filed under: Software Engineering — Promit @ 5:32 pm
Tags: ,

I’m working on some final touches for SlimTune’s next version, and one of them involves persisting the launcher settings between application runs. Launching is handled by an interface ILauncher, which can be set to any number of things via a reflected list of inherited types. A PropertyGrid is used to configure the settings, and all the underlying code ever sees is the interface. SlimTune’s a plugin based C# app, and this is all pretty standard.

When it came to persisting this data across sessions, I figured it’d be no big deal — I’ll just serialize the object out to isolated storage, and deserialize it again when I need it. There’s one hang-up, though. Serializers (or at least XmlSerializer) can’t handle interfaces! Worse still, the so-called solutions I found online were utterly ludicrous. It turns out this is actually an incredibly easy problem to solve, and mainly involves stopping and thinking about what you’re doing for about five seconds.

Alright, so we can’t serialize an interface, but we can serialize any concrete type. Same goes for the deserialization process. The answer is to simple: store the concrete type with the serialized data.

//save the launcher configuration to isolated storage
var isoStore = IsolatedStorageFile.GetUserStoreForApplication();
using(var configFile = new IsolatedStorageFileStream(ConfigFile, FileMode.Create, FileAccess.Write, isoStore))
{
	var launcherType = m_launcher.GetType();
	//write the concrete type so we know what to deserialize
	string launcherTypeName = launcherType.AssemblyQualifiedName;
	var sw = new StreamWriter(configFile);
	sw.WriteLine(launcherTypeName);

	//write the object itself
	var serializer = new XmlSerializer(launcherType);
	serializer.Serialize(sw, m_launcher);
}

We simply ask the interface to give us its real type, and record it to the file before serializing. Okay, so the result won’t be a legal XML file, but how often is that actually a problem? Now the deserialize side of the equation:

//try and load a launcher configuration from isolated storage
var isoStore = IsolatedStorageFile.GetUserStoreForApplication();
using(var configFile = new IsolatedStorageFileStream(ConfigFile, FileMode.Open, FileAccess.Read, isoStore))
{
	//read the concrete type to deserialize
	var sr = new StreamReader(configFile);
	var launcherTypeName = sr.ReadLine();
	var launcherType = Type.GetType(launcherTypeName, true);

	//read the actual object
	XmlSerializer serializer = new XmlSerializer(launcherType);
	m_launcher = (ILauncher) serializer.Deserialize(sr);
}

Reversing things, we first read the type that was written to file, and reconstruct the actual concrete type that goes with that string. Then we know exactly what to deserialize, and XmlSerializer is happy to oblige.

Now that wasn’t so hard, was it?

6 Comments »

  1. […] Roy shares a KISS way to serialize interfaces with the .NET serializers (with a bit more work it might even be possible to emit valid […]

    Pingback by External Happenings « Sgt. Conker — February 21, 2010 @ 5:25 am | Reply

  2. ick, this solution would be fine however if you used a tag or something for the type name.

    Comment by David Black — February 21, 2010 @ 11:57 am | Reply

    • A tag? I would prefer to embed the type into the XML but the only way I can think of doing that is to serialize to and from an XmlDocument and modify the doc elements manually.

      Comment by Promit — February 21, 2010 @ 12:31 pm | Reply

  3. I havnt done much with XmlSerializer. I wrote my own equivelant, which has better handling for things like this(plus the main reason, it has good versioning support for backward/forward compatability of art assets).

    But isnt it possible to have XmlSerializer output an XML fragment to an XmlWriter? That way you could create a root element, with an attribute which specifies the type.

    Comment by David Black — February 21, 2010 @ 1:23 pm | Reply

    • XmlSerializer can handle an XmlWriter just fine. What’s weird is getting XmlWriter hooked up to an XmlDocument. There’s a couple different approaches but once you’ve got that working, you could simply add an attribute to the top node with the type.

      I’m just saving a private settings file to isolated storage file, so the fact that I’m generally a file that isn’t actually XML anymore doesn’t matter. KISS, right?

      Comment by Promit — February 21, 2010 @ 1:30 pm | Reply

  4. Yeah I guess. Just doesn’t feel right. I would have spent some extra time to make it neat and tidy. But then I have lots of time to write software “The Right Way”, if I never finish what I am working on I will be perfectly happy:-)

    Settings files should probably remain compatible across version, so unless you want to break that compatibility you(or we if there are other contributors) will be stuck with the current system.

    Comment by David Black — February 21, 2010 @ 1:46 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: