title: How can I force the use of an xsi:type attribute?
body: <p>How can I force .NET's XmlSerializer to add an <strong>xsi:type="FooClass"</strong> to a member/node of type <strong><code>FooClass</code></strong>?</p>
  
  <p>The scenario is a currently-released app, where in v.1 :</p>
  
  <ul>
  <li>FooClass inherits FooBaseClass</li>
  <li>FooPropertyA is on FooBaseClass</li>
  <li>FooPropertyB is on FooClass</li>
  <li>FooBaseClass is decorated with [XmlInclude(typeof(FooClass))]</li>
  <li>BazClass has member Foo of type FooBaseClass</li>
  <li>All sets of Baz.Foo are to a FooClass instance</li>
  <li>All usages of Baz.Foo expect FooPropertyB (and so a FooClass instance vs FooBaseClass)</li>
  </ul>
  
  <p><strong>The goal: Remove FooBaseClass entirely, pushing FooBaseClass's members up into FooClass, <em>while maintaining backward serialization compatibility</em></strong></p>
  
  <p><strong>The problem: Then I lose the xsi:type="FooClass" attribute on the Baz.Foo serialization.</strong></p>
  
  <p>In other words the XmlSerializer.Serialize output of</p>
  
  <pre><code>public class BazClass
  {
      public BazClass()
      {
          Foo = new FooClass { A = 5, B = "Hello" };
      }
      public FooClass Foo { get; set; }
  }
  
  public class FooClass
  {
      public int FooPropertyA { get; set; }
      public string FooPropertyB { get; set; }
  }
  </code></pre>
  
  <p>needs to be</p>
  
  <pre><code>&lt;Baz&gt;
      &lt;Foo xsi:type="FooClass"&gt;
          &lt;FooPropertyA&gt;Hello&lt;/FooPropertyA&gt;
          &lt;FooPropertyB&gt;5&lt;/FooPropertyB&gt;
      &lt;/Foo&gt;
  &lt;/Baz&gt;
  </code></pre>
  
  <p>Removing FooBasClass is easy, but then XmlSerializer no longer places xsi:type="FooClass" on Baz/Foo, and so v.1 XmlSerializer.Deserialize instantiates a FooBaseClass instance, not setting FooPropertyB, and assigns it to the Foo property of the parent Baz instance.  Thus, any code which checks whether Baz.Foo is FooClass, or casts directly, fails.</p>
  
  <p>The xsi:type attribute was placed automatically in the v.1 code which was</p>
  
  <pre><code>public class BazClass
  {
      public BazClass()
      {
          Foo = new FooClass { A = 5, B = "Hello" };
      }
      public FooBaseClass Foo { get; set; }
  }
  
  public class FooClass : FooBaseClass
  {
      public string FooPropertyB { get; set; }
  }
  
  [XmlInclude(typeof(FooClass))]    
  public class FooBaseClass
  {
      public int FooPropertyA { get; set; }
  }
  </code></pre>
  
  <p>I think the short answer is that you can't - at least not without implementing I(Xml)Serializable or writing custom serialization code.  However, I'm open to good suggestions.  Meanwhile I have implemented a <del>workaround</del> hack below, and am hoping for something more elegant, or that at least allows me somehow to remove FooBaseClass entirely.</p>
  
  <pre><code>BazClass
  {
      [XmlElement("Foo")]
      public FooBaseClass XmlFoo { get { return Foo; } set { Foo = (StartPicture)value; } }
  
      [XmlIgnore]
      public FooClass Foo { get; set; }
  }    
  
  FooClass : FooBaseClass
  {
      public int FooPropertyB { get; set; }
      public string FooPropertyA { get; set; }
  }
  
  [XmlInclude("FooClass")]
  FooBaseClass
  {
  }
  </code></pre>