Once a programmer decides to implement IXmlSerializable, what are the rules and best practices for implementing it? I've heard that GetSchema() should return null and ReadXml should move to the next element before returning. Are these true? And what about WriteXml: 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.
Here's a sample of what I have now. I'll update it as I get good responses.
public class Calendar: IEnumerable<Gvent>, IXmlSerializable
{
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
if (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "Calendar")
{
_Name = reader["Name"];
_Enabled = Boolean.Parse(reader["Enabled"]);
_Color = Color.FromArgb(Int32.Parse(reader["Color"]));
if (reader.ReadToDescendant("Event"))
{
while (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "Event")
{
var evt = new Event();
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 (var evt in _Events)
{
writer.WriteStartElement("Event");
evt.WriteXml(writer);
writer.WriteEndElement();
}
}
}
public class Event : IXmlSerializable
{
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
if (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "Event")
{
_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());
}
}