Internally, according to the docs, the state server uses BinaryFormatter
to serialize complex types. BinaryFormatter
serializes all public and private fields (not properties!) of a class or struct that is marked as [Serializable]
. But XmlDocument
, as you have noted, is not so marked, thus cannot be immediately serialized with BinaryFormatter
.
XmlDocument
can, however, be trivially converted from and to a string -- the XML itself that the document represents. Thus if the XmlDocument
field were contained in a type implementing ISerializable
, then its GetObjectData()
could simply store the corresponding XML string inside the serialization stream. Then the corresponding serialization constructor could extract the XML string and reconstitute the XmlDocument
.
Since implementing ISerializable
on a pre-existing class can be time consuming, the easiest way to accomplish what you want would be to introduce a small serialization wrapper struct for your XML documents:
[Serializable]
public struct XmlDocumentSerializationWrapper : ISerializable
{
public static implicit operator XmlDocumentSerializationWrapper(XmlDocument data) { return new XmlDocumentSerializationWrapper(data); }
public static implicit operator XmlDocument(XmlDocumentSerializationWrapper wrapper) { return wrapper.XmlDocument; }
private readonly XmlDocument xmlDocument;
public XmlDocument XmlDocument { get { return xmlDocument; } }
public XmlDocumentSerializationWrapper(XmlDocument xmlDocument)
{
this.xmlDocument = xmlDocument;
}
public XmlDocumentSerializationWrapper(SerializationInfo info, StreamingContext context)
{
var xml = (string)info.GetValue("XmlDocument", typeof(string));
if (!string.IsNullOrEmpty(xml))
{
xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
}
else
{
xmlDocument = null;
}
}
#region ISerializable Members
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
if (XmlDocument != null)
{
var xml = XmlDocument.OuterXml;
info.AddValue("XmlDocument", xml);
}
else
{
info.AddValue("XmlDocument", (string)null);
}
}
#endregion
}
Then, in the classes you want to serialize, replace your XmlDocument
fields (and auto-implemented properties) with wrapper struct fields, e.g.:
[Serializable]
public class TestClass
{
XmlDocumentSerializationWrapper doc;
public XmlDocument Document { get { return doc; } set { doc = value; } }
}
The implicit operators in the struct handle automatic conversion from and to the wrapper.