title: Polymorphic Types and IXmlSerializable
body: <p>The XML serialization in .NET allows polymorphic objects through the <code>extraTypes[]</code> parameter of the <code>XmlSerializer</code> constructor. It also allows customization of XML serialization for types that implement <code>IXmlSerializable</code>.</p>
  
  <p>However, I’m unable to combine these two features – as demonstrated in this minimal example:</p>
  
  <pre><code>using System;
  using System.IO;
  using System.Xml;
  using System.Xml.Schema;
  using System.Xml.Serialization;
  
  namespace CsFoo
  {
      public class CustomSerializable : IXmlSerializable
      {
          public XmlSchema GetSchema() { return null; }
          public void ReadXml(XmlReader xr) { }
          public void WriteXml(XmlWriter xw) { }
      }
  
      class CsFoo
      {
          static void Main()
          {
              XmlSerializer xs = new XmlSerializer(
                  typeof(object),
                  new Type[] { typeof(CustomSerializable) });
  
          xs.Serialize(new StringWriter(), new CustomSerializable());
      }
  }
  </code></pre>
  
  <p>The last line throws <code>System.InvalidOperationException</code> with this message:</p>
  
  <blockquote>
    <p>The type CsFoo.CustomSerializable may not be used in this context to
    use CsFoo.CustomSerializable as a parameter, return
    type, or member of a class or struct, the parameter, return
    type, or member must be declared as type CsFoo.CustomSerializable
    (it cannot be object). Objects of type CsFoo.CustomSerializable
    may not be used in un-typed collections, such as ArrayLists.</p>
  </blockquote>
  
  <p>Wading through the dynamically generated XML assemblies, we ultimately come back to .NET standard library code by calling:</p>
  
  <pre><code>System.Xml.Serialization.XmlSerializationWriter.WriteTypedPrimitive(
       String, String, Object, Boolean) : Void
  </code></pre>
  
  <p>In turn, this leads to:</p>
  
  <pre><code>protected Exception CreateUnknownTypeException(Type type)
  {
      if (typeof(IXmlSerializable).IsAssignableFrom(type))
      {
          return new InvalidOperationException(
              Res.GetString("XmlInvalidSerializable",
              new object[] { type.FullName }));
      }
  
      // Rest omitted...
  </code></pre>
  
  <p>Reflector shows that the <code>XmlInvalidSerializable</code> resource corresponds with the string above – i.e.,  <code>WriteTypedPrimitive</code> doesn’t like <code>IXmlSerializable</code>.</p>
  
  <p>If we generate a non-polymorphic serializer, like so:</p>
  
  <pre><code>XmlSerializer xs = new XmlSerializer(typeof(CustomSerializable));
  </code></pre>
  
  <p>.NET will generate a call to:</p>
  
  <pre><code>System.Xml.Serialization.XmlSerializationWriter.WriteSerializable(
      IXmlSerializable, String, String, Boolean) : Void 
  </code></pre>
  
  <p>This handles <code>IXmlSerializable</code> properly. Does anybody know why .NET doesn’t use this function in the polymorphic case? Looking at the C# that the XML serializer generates, it appears to me this can be done quite easily. Here's some code I got from the XML serializer, with an untested solution:</p>
  
  <pre><code>void Write1_Object(string n, string ns, global::System.Object o, 
     bool isNullable, bool needType)
  {
      if ((object)o == null)
      {
          if (isNullable) WriteNullTagLiteral(n, ns);
          return;
      }
      if (!needType)
      {
          System.Type t = o.GetType();
          if (t == typeof(global::System.Object))
          {
          }
  &gt;&gt;&gt; patch begin &lt;&lt;&lt;
  +         else if (typeof(IXmlSerializable).IsAssignableFrom(t))
  +         {
  +             WriteSerializable((System.Xml.Serialization.IXmlSerializable)
                     ((global::CsFoo.CustomSerializable)o), 
  +                  @"CustomSerializable", @"", true, true);
  +         }
  &gt;&gt;&gt; patch end &lt;&lt;&lt;
          else
          {
              WriteTypedPrimitive(n, ns, o, true);
              return;
          }
      }
      WriteStartElement(n, ns, o, false, null);
      WriteEndElement(o);
  }
  </code></pre>
  
  <p>Is this left out for technical reasons or just a feature limitation? Unsupported feature, or my idiocy? My intertubes Google skills fail me.</p>
  
  <p>I did find some related questions here, with "<a href="https://stackoverflow.com/questions/527902/c-xml-serializing-a-derived-class-using-ixmlserializable">C# Xml-Serializing a derived class using IXmlSerializable</a>" being most relevant. It leads me to believe that it's simply not possible.</p>
  
  <p>In that case, my current thought is to inject a default <code>IXmlSerializable</code> implementation in the root base class. Then everything will be an <code>IXmlSerializable</code>, and .NET won't complain. I can use Reflection.Emit to whip out the <code>ReadXml</code> and <code>WriteXml</code> bodies for each concrete types, generating XML that would look the same as it would if I used the library one.</p>
  
  <p>Some people, when confronted with an XML serialization problem, think "I know, I'll use Reflection.Emit to generate code." Now they have two problems.</p>
  
  <hr>
  
  <p>P.S. Note; I'm aware of alternatives to .NET's XML serialization, and know it has limitations. I also know that saving a POCO is vastly simpler than dealing with abstract data types. But I've got a pile of legacy code, and need support for existing XML schemas.</p>
  
  <p>So while I appreciate replies that show how easy this is in <code>SomeOtherXML</code>, <code>YAML</code>, <code>XAML</code>, <code>ProtocolBuffers</code>, <code>DataContract</code>, <code>RandomJsonLibrary</code>, <code>Thrift</code>, or your <code>MorseCodeBasedSerializeToMp3</code> library - hey I might learn something -, what I'm hoping for is an XML serializer work-around, if not solution.</p>