My question is probably arising from a basic misunderstanding of XML serialization, but anyways...
I\'m trying to serialize a class containing an object which was initialize
Your difficulty arises from the fact that XmlSerializer
requires all types to be serialized to be discoverable statically, through reflection. However, your type MyClass
has a polymorphic object
property where a instance of a subtype of object
-- specifically string []
-- is being stored. When XmlSerializer
encounters it, since objects of this type are not expected, the serializer throws the exception you see.
When serializing polymorphic properties such as this, it is necessary to use XML serialization attributes to declare the types that can be encountered. XmlSerializer
provides two mechanisms to accomplish this.
Declare the possible polymorphic subtypes using XmlInclude(Type) attributes on the containing type. Since string
and string []
are the possible types of your object
property, you would do:
[XmlInclude(typeof(string))]
[XmlInclude(typeof(string[]))]
public class MyClass
{
public object myObject { get; set; }
public MyClass()
{
myObject = new string[] { "somestring" };
}
}
And the resulting XML will look like:
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<myObject xsi:type="ArrayOfString">
<string>somestring</string>
</myObject>
</MyClass>
Notice the xsi:type attribute? That is a w3c standard attribute that allows the element to assert its type explicitly. Its presence allows XmlSerializer
to deserialize the XML into the same type of objects as were originally serialized.
(Note that [XmlInclude(typeof(string))]
seems to be unnecessary as string
is apparently a built-in known type - though I cannot find documentation confirming this.)
Declare the possible polymorphic subtypes using [XmlElement(String, Type)] on the polymorphic property itself. Thus you would do something like:
public class MyClass
{
[XmlElement("myObjectString", typeof(string))]
[XmlElement("myObjectStringArray", typeof(string[]))]
public object myObject { get; set; }
public MyClass()
{
myObject = new string[] { "somestring" };
}
}
And the XML generated will look like:
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<myObjectStringArray>
<string>somestring</string>
</myObjectStringArray>
</MyClass>
Notice that the name of the myObject
element been modified to the string passed to into the [XmlElement(String, Type)]
attribute constructor. This allows XmlSerializer
to deserialize the XML into the same type of objects as were originally serialized.