I've got a simple class that inherits from Collection and adds a couple of properties. I need to serialize this class to XML, but the XMLSerializer ignores my additional properties.
I assume this is because of the special treatment that XMLSerializer gives ICollection and IEnumerable objects. What's the best way around this?
Here's some sample code:
using System.Collections.ObjectModel;
using System.IO;
using System.Xml.Serialization;
namespace SerialiseCollection
{
class Program
{
static void Main(string[] args)
{
var c = new MyCollection();
c.Add("Hello");
c.Add("Goodbye");
var serializer = new XmlSerializer(typeof(MyCollection));
using (var writer = new StreamWriter("test.xml"))
serializer.Serialize(writer, c);
}
}
[XmlRoot("MyCollection")]
public class MyCollection : Collection<string>
{
[XmlAttribute()]
public string MyAttribute { get; set; }
public MyCollection()
{
this.MyAttribute = "SerializeThis";
}
}
}
This outputs the following XML (note MyAttribute is missing in the MyCollection element):
<?xml version="1.0" encoding="utf-8"?>
<MyCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>Hello</string>
<string>Goodbye</string>
</MyCollection>
What I want is
<MyCollection MyAttribute="SerializeThis"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>Hello</string>
<string>Goodbye</string>
</MyCollection>
Any ideas? The simpler the better. Thanks.
I've been fighting with the same issue Romaroo is (wanting to add properties to the xml serialization of a class that implements ICollection). I have not found any way to expose properties that are in the collection class. I even tried using the XmlAttribute tag and making my properties show up as attributes of the root node, but no luck there either. I was however able to use the XmlRoot tag on my class to rename it from "ArrayOf...". Here are some references in case you're interested:
Collections generally don't make good places for extra properties. Both during serialization and in data-binding, they will be ignored if the item looks like a collection (
IList
,IEnumerable
, etc - depending on the scenario).If it was me, I would encapsulate the collection - i.e.
The other option is to implement
IXmlSerializable
(quite a lot of work), but that still won't work for data-binding etc. Basically, this isn't the expected usage.Sometimes you just want to do what you just want to do; the Framework be damned.
I posted an answer here Property of a List<T> Not Deserialized
that does what the OP wanted to do.
If you do encapsulate, as Marc Gravell suggests, the beginning of this post explains how to get your XML to look exactly like you describe.
http://blogs.msdn.com/youssefm/archive/2009/06/12/customizing-the-xml-for-collections-with-xmlserializer-and-datacontractserializer.aspx
That is, instead of this:
You can have this:
As Neil Whitaker suggests and in case his link dies..
Create an inner collection to store the strings and apply the XmlElement attribute to mask the collection name. Produces the same xml output as if MyCollection inherited from Collection, but also serializes attributes on the parent element.