I am trying to do a very simple bit of serialization with XmlSerializer:
public struct XmlPerson
{
[XmlAttribute] public string Id { get; set; }
[XmlAttribute] public string Name { get; set; }
}
public class GroupOfPeople
{
private Dictionary<string, string> _namesById = new Dictionary<string, string>();
//pseudo property for serialising dictionary to/from XML
public List<XmlPerson> _XmlPeople
{
get
{
var people = new List<XmlPerson>();
foreach (KeyValuePair<string, string> pair in _namesById )
people.Add(new XmlPerson() { Id = pair.Key, Name = pair.Value });
return people;
}
set
{
_namesById.Clear();
foreach (var person in value)
_namesById.Add(person.Id, person.Name);
}
}
}
Saving this class works fine, and I get:
<?xml version="1.0" encoding="utf-8"?>
<GroupOfPeople xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<_XmlPeople>
<XmlPerson Id="person1" Name="Fred" />
<XmlPerson Id="person2" Name="Bill" />
<XmlPerson Id="person3" Name="Andy" />
<XmlPerson Id="person4" Name="Nagesh" />
</_XmlPeople>
</GroupOfPeople>
However, when I read in the file again, my _XmlPeople property setter is never called, and thus the dictionary is empty. All other properties on this object get deserialized fine.
Am I missing something obvious? I have tried various collection types but none of them deserialize.
EDIT: Read code:
try
{
using (var stream = new StreamReader(itemPath))
{
var xml = new XmlSerializer(typeof(GroupOfPeople));
GroupOfPeople item = (GroupOfPeople)xml.Deserialize(stream);
}
}
//snip error stuff
Answer for clarity:
Have done some debugging and found that XmlSerializer
does not call the setter for a collection.
Instead is calls the getter, and then adds items to the collection returned. Thus a solution such as Felipe's is necessary.
Have you tried using the XmlArray attribute?
With your example it would be something like this:
[XmlArray]
[XmlArrayItem(ElementName="XmlPerson")]
public List<XmlPerson> XmlPeople
EDIT:
Here, try the following structure:
public struct XmlPerson
{
[XmlAttribute] public string Id { get; set; }
[XmlAttribute] public string Name { get; set; }
}
public class GroupOfPeople
{
[XmlArray]
[XmlArrayItem(ElementName="XmlPerson")]
public List<XmlPerson> XmlPeople { get; set; }
}
I don't think it will be easy to add code to the Setter of the list, so what about getting that Dictionary when you actually need it?
Like this:
private Dictionary<string, string> _namesById;
public Dictionary<string, string> NamesById
{
set { _namesById = value; }
get
{
if (_namesById == null)
{
_namesById = new Dictionary<string, string>();
foreach (var person in XmlPeople)
{
_namesById.Add(person.Id, person.Name);
}
}
return _namesById;
}
}
This way you'll get the items from the XML and will also mantain that Dictionary of yours.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With