title: Proper way to implement IXmlSerializable?
body: <p>Once a programmer decides to implement <code>IXmlSerializable</code>, what are the rules and best practices for implementing it? I've heard that <code>GetSchema()</code> should return <code>null</code> and <code>ReadXml</code> should move to the next element before returning. Is this true? And what about <code>WriteXml</code> - should it write a root element for the object or is it assumed that the root is already written? How should child objects be treated and written?</p>
  
  <p>Here's a sample of what I have now. I'll update it as I get good responses.</p>
  
  <pre><code>public class MyCalendar : IXmlSerializable
  {
      private string _name;
      private bool _enabled;
      private Color _color;
      private List&lt;MyEvent&gt; _events = new List&lt;MyEvent&gt;();
  
  
      public XmlSchema GetSchema() { return null; }
  
      public void ReadXml(XmlReader reader)
      {
          if (reader.MoveToContent() == XmlNodeType.Element &amp;&amp; reader.LocalName == "MyCalendar")
          {
              _name    = reader["Name"];
              _enabled = Boolean.Parse(reader["Enabled"]);
              _color   = Color.FromArgb(Int32.Parse(reader["Color"]));
  
              if (reader.ReadToDescendant("MyEvent"))
              {
                  while (reader.MoveToContent() == XmlNodeType.Element &amp;&amp; reader.LocalName == "MyEvent")
                  {
                      MyEvent evt = new MyEvent();
                      evt.ReadXml(reader);
                      _events.Add(evt);
                  }
              }
              reader.Read();
          }
      }
  
      public void WriteXml(XmlWriter writer)
      {
          writer.WriteAttributeString("Name",    _name);
          writer.WriteAttributeString("Enabled", _enabled.ToString());
          writer.WriteAttributeString("Color",   _color.ToArgb().ToString());
  
          foreach (MyEvent evt in _events)
          {
              writer.WriteStartElement("MyEvent");
              evt.WriteXml(writer);
              writer.WriteEndElement();
          }
      }
  }
  
  public class MyEvent : IXmlSerializable
  {
      private string _title;
      private DateTime _start;
      private DateTime _stop;
  
  
      public XmlSchema GetSchema() { return null; }
  
      public void ReadXml(XmlReader reader)
      {
          if (reader.MoveToContent() == XmlNodeType.Element &amp;&amp; reader.LocalName == "MyEvent")
          {
              _title = reader["Title"];
              _start = DateTime.FromBinary(Int64.Parse(reader["Start"]));
              _stop  = DateTime.FromBinary(Int64.Parse(reader["Stop"]));
              reader.Read();
          }
      }
  
      public void WriteXml(XmlWriter writer)
      {
          writer.WriteAttributeString("Title", _title);
          writer.WriteAttributeString("Start", _start.ToBinary().ToString());
          writer.WriteAttributeString("Stop",  _stop.ToBinary().ToString());
      }
  }
  </code></pre>
  
  <p>Corresponding Sample XML</p>
  
  <pre><code>&lt;MyCalendar Name="Master Plan" Enabled="True" Color="-14069085"&gt;
      &lt;MyEvent Title="Write Code" Start="-8589241828854775808" Stop="-8589241756854775808" /&gt;
      &lt;MyEvent Title="???" Start="-8589241828854775808" Stop="-8589241756854775808" /&gt;
      &lt;MyEvent Title="Profit!" Start="-8589247048854775808" Stop="-8589246976854775808" /&gt;
  &lt;/MyCalendar&gt;
  </code></pre>