When a class is inherited from List<>, XmlSerializer doesn't serialize other attributes
I'm having a situation here, I need my class to be inherited from List<ItemType>
, but when I do this XmlSerializer does not serialize any property or field declared in my class, the following sample demonstrates:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DoSerialize();
}
private void DoSerialize()
{
MyClass obj = new MyClass();
obj.Add(1);
obj.Add(2);
obj.Add(3);
XmlSerializer s = new XmlSerializer(typeof(MyClass));
StringWriter sw = new StringWriter();
s.Serialize(sw, obj);
}
}
[Serializable]
[XmlRoot]
public class MyClass : List<int>
{
public MyClass()
{
}
int myAttribute = 2011;
[XmlAttribute]
public int MyAttribute
{
get
{
开发者_运维知识库 return myAttribute;
}
set
{
myAttribute = value;
}
}
}
the resulting XML:
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<int>1</int>
<int>2</int>
<int>3</int>
</ArrayOfInt>
This is by design. I don't know why this decision was made, but it is stated in the documentation:
- Classes that implement ICollection or IEnumerable. Only collections are serialized, not public properties.
(Look under "Items that can be serialized" section). Someone has filed a bug against this, but it won't be changed - here, Microsoft also confirms that not including the properties for classes implementing ICollection
is in fact the behaviour of XmlSerializer.
A workaround would be to either:
- Implement
IXmlSerializable
and control serialization yourself.
or
- Change MyClass so it has a public property of type List (and don't subclass it).
or
- Use DataContractSerializer, which handles this scenario.
Here's a though for you to consider.
You can have a class that is a container class like this:
class ContainerObject
{
public int MyNewProperty { get; set; }
[XmlElement("")]
public List<int> MyList { get; set; }
}
The trick is to have XmlElement name = "" above the List element.
When this is serialized into xml, you will have:
<ContainerObject>
<MyNewProperty>...</MyNewProperty>
<int>...</int>
<int>...</int>
</ContainerObject>
If you like, you can also create another class for items in a list
class MyItem
{
public int MyProperty {get;set;}
}
and then instead of having List of ints, have a List of MyItems.
This was you control XmlElement name of every item in a list.
I hope this was helpful.
精彩评论