XML反序列化IEnumerable类时出现错误

3

我正在尝试将HistoryRoot类序列化和去序列化为以下XML格式:

<?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>

这里有HistoryRoot、HistoryList和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;
}

这是我遇到错误的地方:

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}
我该如何解决这个错误?谢谢!

2个回答

3
为了使用 XmlSerializer 序列化或反序列化实现 IEnumerable 接口的类,你的类必须有一个 Add 方法。根据文档所述,XmlSerializer 对实现 IEnumerable 或 ICollection 的类进行特殊处理。实现 IEnumerable 接口的类必须实现一个公共的 Add 方法,该方法接受一个参数。Add 方法的参数类型必须与从 GetEnumerator 返回的值的 Current 属性返回的类型相同,或者是该类型的基类之一。
即使您只想进行序列化而不进行反序列化,也必须拥有此方法,因为 XmlSerializer 会同时进行运行时代码生成,用于序列化和反序列化。
这个方法实际上不需要在序列化成功后工作,它只需要存在即可。
    public void Add(object obj)
    {
        throw new NotImplementedException();
    }

(当然,要使反序列化成功,必须实现该方法。)

谢谢你的帮助,我已经修复了 :) - Thanh Nguyen

1
尽管sbc的答案是正确的,并且我已经接受了它,但现在我将HistoryList类更改为以下方式,使之更加容易:
public class HistoryList : List<HistoryItem> //   <-- Add List<HistoryItem>
{    
    [XmlIgnore]
    public SortedList<DateTime, string> sl;

    [XmlIgnore]
    public int max;

    [XmlIgnore]
    public ComboBox c;
}

然后将 HistoryRoot 改为:
[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
    },
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接