Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error with XML deserialization an IEnumerable class

I'm trying to serial and deresial HistoryRoot class to 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 HistoryRoot, HistoryList and HistoryItem class:

[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;
}

This is where I get the error:

using (FileStream fs = new FileStream("filepath.xml", FileMode.Open))
    {
        XmlSerializer serializer = new XmlSerializer(typeof(HistoryRoot));
        HistoryRoot h = (HistoryRoot)serializer.Deserialize(fs);
    }

"There was an error reflecting type 'History.HistoryRoot'." System.Exception {System.InvalidOperationException}
How I can fix this error? Thank!

like image 375
Thanh Nguyen Avatar asked Sep 08 '26 03:09

Thanh Nguyen


1 Answers

In order to serialize or deserialize a class that implements IEnumerable using XmlSerializer, your class must have an Add method. From the documentation:

The XmlSerializer gives special treatment to classes that implement IEnumerable or ICollection. A class that implements IEnumerable must implement a public Add method that takes a single parameter. The Add method's parameter must be of the same type as is returned from the Current property on the value returned from GetEnumerator, or one of that type's bases.

You must have this method even if you never deserialize and only serialize, because XmlSerializer does run-time code generation for both serialization and deserialization at the same time.

The method doesn't actually have to work for serialization to succeed, it just needs to be present:

    public void Add(object obj)
    {
        throw new NotImplementedException();
    }

(Of course, for deserialization to succeed, the method must needs be implemented.)

like image 139
dbc Avatar answered Sep 10 '26 16:09

dbc