Error with XML deserialization of IEnumerable class
I'm trying to use serial and dereryial HistoryRoot for this XML format:
<?xml version="1.0"?>
<HistoryRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Files>
<HistoryItem d="2015-06-21T17:40:42" s="file:///D:\cars.txt" />
</Files>
<Folders>
<HistoryItem d="2015-06-21T17:40:42" s="D:\fc\Cars" />
</Folders>
</HistoryRoot>
Here is a list of HistoryRoot, HistoryList and HistoryItem:
[Serializable]
public class HistoryRoot
{
public HistoryList
Files = new HistoryList
{
sl = new SortedList<DateTime, string>(),
list = new List<HistoryItem>(),
max = 500,
c = program.M.qFile
},
Folders = new HistoryList
{
sl = new SortedList<DateTime, string>(),
list = new List<HistoryItem>(),
max = 100,
c = program.M.qFolder
},
}
[Serializable]
public class HistoryList : IEnumerable
{
[XmlIgnore]
public List<HistoryItem> list;
[XmlIgnore]
public SortedList<DateTime, string> sl;
[XmlIgnore]
public int max;
[XmlIgnore]
public ComboBox c;
public IEnumerator GetEnumerator()
{
if (list == null) list = new List<HistoryItem>();
return list.GetEnumerator();
}
}
public struct HistoryItem
{
[XmlAttribute("d")]
public DateTime D;
[XmlAttribute("s")]
public string S;
}
Here I am getting an error:
using (FileStream fs = new FileStream("filepath.xml", FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(HistoryRoot));
HistoryRoot h = (HistoryRoot)serializer.Deserialize(fs);
}
"An error has occurred that reflects the type 'History.HistoryRoot'." System.Exception {System.InvalidOperationException}
How can I fix this error? Thank!
source to share
To serialize or deserialize a class that implements IEnumerable
with XmlSerializer
, your class must have a method Add
. From the documentation :
The XmlSerializer provides a special call to classes that implement IEnumerable or ICollection. A class that implements IEnumerable must implement the public Add method that takes one parameter. The Add method parameter must be the same type as returned from the Current property for the value returned from GetEnumerator or one of the databases of that type.
You should have this method even if you never deserialize and only serialize, because it XmlSerializer
creates runtime generations for both serialization and deserialization at the same time.
It doesn't really need to work for serialization, but just needs to be present:
public void Add(object obj)
{
throw new NotImplementedException();
}
(Of course, this method must be implemented for de serialization to succeed .)
source to share
Although sbc's answer is correct and I accepted it, I now change the class HistoryList
to make it easier:
public class HistoryList : List<HistoryItem> // <-- Add List<HistoryItem>
{
[XmlIgnore]
public SortedList<DateTime, string> sl;
[XmlIgnore]
public int max;
[XmlIgnore]
public ComboBox c;
}
Then change the value HistoryRoot
to:
[Serializable]
public class HistoryRoot
{
public HistoryList
Files = new HistoryList
{
sl = new SortedList<DateTime, string>(),
//list = new List<HistoryItem>(), <-- Remove this line
max = 500,
c = program.M.qFile
},
Folders = new HistoryList
{
sl = new SortedList<DateTime, string>(),
//list = new List<HistoryItem>(), <-- Remove this line
max = 100,
c = program.M.qFolder
},
}
source to share