I want to deserialize serialized XML containing collection of CDATA.
XML looks like this:
<User Index="1">
<Address><![CDATA[My street 1, 1234, My city]]></Address>
<Address><![CDATA[My next street 1, 5678, My another city]]></Address>
</User>
Since I want to add new address directly as string like this:
var user = new User();
user.Addresses.Add("My street 1, 1234, My city");
user.Addresses.Add("My next street 1, 5678, My another city");
my user class looks like that:
[XmlRoot("User", IsNullable = true)]
public class User
{
[XmlIgnore]
private XmlDocument xmlDoc;
[XmlIgnore]
private Collection<string> addresses;
[XmlIgnore]
private Collection<XmlNode> addressesNode;
public User()
{
xmlDoc = new XmlDocument();
addresses = new Collection<string>();
}
[XmlAttribute("Index")]
public int Index { get; set; }
[XmlElement("Address", IsNullable = true)]
public Collection<XmlNode> AddressesNode
{
get
{
// This will create CDATA in address node. String values for
// CDATA are in addresses collection.
// This is causing problem.
return new Collection<XmlNode>(addresses.Select(a => xmlDoc.CreateCDataSection(a)).ToArray());
}
set
{
// Set also address collection of string to the same values.
addresses = new Collection<string>(value.Select(a => a.Value).ToArray());
addressesNode = value;
}
}
[XmlIgnore]
public Collection<string> Addresses
{
get
{
return addresses;
}
}
}
Serializing this works fine. But while deserializing, exception is thrown
"Collection is read-only."
When you create a new Collection passing the IList as a parameter, it creates the collection as a wrapper around the original list. It does NOT copy it to a new list (see here). In your addressNode setter, you create a new collection as a wrapper around your collection. You may change this to a new List instead, since the List constructor does create a new list rather than wrapping the original one (see here).