More on XmlSerializer

Last month, I blogged about XmlSerializer, and the constraints it imposes on the .NET types you'd like to map onto XML structure.  I was recently reminded of another limitation of XmlSerializer:  it doesn't let you switch your type mappings, on the fly -- for example, in response to a version attribute.  And yet.  A great many XML document formats use just such an attribute!  Here's an example, from Visual Studio's own .csproj file format -- it seems they like to serialize both the product- and schema-version numbers, for good measure:

<VisualStudioProject>
    <CSHARP
        ProjectType = "Local"
        ProductVersion = "7.10.3077"
        SchemaVersion = "2.0"
        ...

Why doesn't XmlSerializer allow us to switch our type mappings, after we see the version number?  The reason is simple, although not immediately apparent: XmlSerializer is a compiler.

Ever wonder why you must specify the root element's .NET type, at instantiation-time?  And what is that extraTypes parameter all about -- why doesn't XmlSerializer simply call Object.GetType() at run-time, and do the right thing?  It's because XmlSerializer wants to generate the complete code for serialization, beforehand -- so it's got to know the complete set of types it can expect to face.

This design offers fantastic throughput, for high-volume serialization scenarios like web service backends -- but it comes at the cost of some run-time flexibility, for scenarios like deserialization of versioned document types.

Now, if your XML schema has only trivial differences among versions (eg: the addition of an attribute or element, here or there) you can probably just get away with using the latest version's type mappings -- when deserializing an older instance document, the missing elements and attributes will be initialized to their default values -- no exceptions are thrown.  But for less trivial changes in schema, there's just no easy way to tell the XmlSerializer "hey, if you see a version attribute with a value less than 4.7, back up and start over with this older set of .NET types".

Of course, it's a free country: you can use XmlDocument or XmlReader to peek ahead for the version attribute, then back up and start over in earnest with a properly initialized XmlSerializer -- but just how terribly inefficient that is depends on where you're getting your XML from, and how large it is.  FileStream?  Not too bad.  NetworkStream?  Terrible.

Updated: Tue, 06 Jan 2004 14:35:00 GMT