Anonymous type XML serialization

I ran into an issue recently with the C# XML serializer. There was a fair bit of indirection, but it boiled down to this code snippet:

</pre>
<span style="font-weight: 400;">static string ToXml(object toSerialize){</span>

<span style="font-weight: 400;">XmlSerializer x = new XmlSerializer(toSerialize.GetType());</span>

<span style="font-weight: 400;">var results = new StringWriter();</span>

<span style="font-weight: 400;">    </span> <span style="font-weight: 400;">x.Serialize(results, toSerialize);</span>

<span style="font-weight: 400;">return results.ToString();</span>

<span style="font-weight: 400;">}</span>

<span style="font-weight: 400;">ToXml(new {item = "thing"});

 

That snippet results in the following error:

Run-time exception (line 15): <>f__AnonymousType0`1[System.String] cannot be serialized because it does not have a parameterless constructor.

I checked using reflection that the anonymous type has a single constructor that takes a string, as you would expect based on the lack of a parameterless one. That being the case, it makes sense that you can’t use the XmlSerializer against it since it doesn’t match the required interface. But, this brought up the question: if it matched, would the XmlSerializer accept it? There is a request out at user voice to enable this and there is a comment that implies it wouldn’t be simple. So I set out to find out whether or not it was a simple fix.

I opened up the intermediate language representation of the type and tried editing it to add the constructor. This quickly turned out to be beyond my current understanding of intermediate language. In doing research on intermediate language, I found a bigger issue – anonymous types are read-only. I had never even considered they wouldn’t be writable. This is a big deal because the XmlSerializer will not serialize read-only properties. Only enabling a parameterless constructor wouldn’t enable serialization unless the anonymous type was further changed. So, I endeavored to change the fake anonymous type to be read-write as well.

Overall this is all of the changes I made:

  1. Added parameterless constructor
  2. Added assembly declaration
  3. Removed the <> token which indicates a compiler generated class
  4. Changed the class to public
  5. Fixed the assembly declaration since it didn’t match the file name
  6. Removed initonly from the field
  7. Built the set half of the property and it’s backing method

Overall, it was easier than I thought it would be, and it does serialize once you make all of these changes. Check out the IL code here. Unfortunately, this sort of change will never get folded back into the mainline anonymous types, since breaking immutability would mean you can’t use them as keys for hashes anymore. Tuples don’t serialize either for the same reasons, maybe they could be extended, but then you can’t name the fields.

Advertisements

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