XmlSerializer.Deserialize()未正确反序列化List

我是C#XmlSerializer的新手,所以我可能会遗漏一些基本的东西。

我遇到的问题是我有一个类有另一个类的List 。 当我序列化主类时,XML看起来很漂亮,所有数据都完好无损。 当我反序列化XML时, List的数据消失了,我留下了一个空的List 。 我没有收到任何错误,序列化部分就像魅力一样。

反序列化过程中我错过了什么?

编辑:请注意,下面显示的代码不能重现问题 – 它的工作原理。 这是真实代码的简化版本,但不起作用。 不幸的是,下面的代码已经足够简化,无法重现问题!

 public class User { public User() { this.Characters = new List(); } public string Username { get; set; } public List Characters { get; set; } } public class Character { public Character() { this.Skills = new List(); } public string Name { get; set; } public List Skills { get; set; } } public enum Skill { TreeClimber, ForkliftOperator } public static void Save(User user) { using (var textWriter = new StreamWriter("data.xml")) { var xmlSerializer = new XmlSerializer(typeof(User)); xmlSerializer.Serialize(textWriter, user); } } public static User Restore() { if (!File.Exists("data.xml")) throw new FileNotFoundException("data.xml"); using (var textReader = new StreamReader("data.xml")) { var xmlSerializer = new XmlSerializer(typeof(User)); return (User)xmlSerializer.Deserialize(textReader); } } public void CreateAndSave() { var character = new Character(); character.Name = "Tranzor Z"; character.Skills.Add(Skill.TreeClimber); var user = new User(); user.Username = "Somebody"; user.Characters.Add(character); Save(user); } public void RestoreAndPrint() { var user = Restore(); Console.WriteLine("Username: {0}", user.Username); Console.WriteLine("Characters: {0}", user.Characters.Count); } 

通过执行CreateAndSave()生成的XML如下所示:

  Somebody   Tranzor Z  TreeClimber     

完善! 这就是应该看的样子。 如果我然后执行RestoreAndPrint()我得到一个User对象,其Username属性设置正确但Characters属性是一个空列表:

 Username: Somebody Characters: 0 

任何人都可以向我解释为什么Characters属性被正确序列化但不会反序列化?

无法重现; 我得到(在修复更直接的错误之后):

 Username: Somebody Characters: 1 

变化:

  • WriteLine而不是WriteFormat (阻止它编译)
  • 初始化默认构造函数中的列表(阻止CreateAndSave工作):
    • public User() { Characters = new List(); }
    • public Character() { Skills = new List(); }

过去,在序列化列表时,我使用了[XmlArray]和[XmlArrayItem]注释。 然后,您将在Characters属性上放置一个[XmlIgnore]注释。 在你的情况下,它看起来像这样:

 [XmlArray("Characters")] [XmlArrayItem("Character", Type=typeof(Character))] public Character[] _ Characters { get { //Make an array of Characters to return return Characters.ToArray(); } set { Characters.Clear(); for( int i = 0; i < value.Length; i++ ) Characters.Add( value[i] ); } } 

希望有所帮助。

也许,而不是StreamReader,而是创建一个XmlReader。 此外,作为故障排除步骤,您可以尝试使用显式类型(如下所示)而不是“var”声明的现有代码。

 public static User Restore() { if (!File.Exists("data.xml")) throw new FileNotFoundException("data.xml"); XmlReader xr = XmlReader.Create("data.xml"); XmlSerializer serializer = new XmlSerializer(typeof(User)); var user = (User)serializer.Deserialize(xr); xr.Close(); return user; } 

编辑:此外,尝试在您的User类上的XmlInclude批注。

 [XmlInclude( typeof( Character ) )] 

经过长时间的代码考虑后,我终于放弃了使用XmlSerializer的默认行为的想法。

所有相关的类现在都inheritance了IXmlSerializer并实现了ReadXml()和WriteXml()函数。 我真的希望采取懒惰的路线,但现在我已经玩过IXmlSerializer,我意识到它真的不难,增加的灵活性非常好。

我知道这是旧的,但我有同样的问题。

我发现如果我有一个在图中实现IXmlSerializable的对象(所以我想要反序列化的主要对象不要实现接口,但是它中的对象实现了它),它会破坏所有的反序列化。 列表不再反序列化,也不是我正在谈论的对象。 序列化工作完美。

 Stream stream = File.Open(filename + ".xml", FileMode.Open); User user = null; using (XmlReader reader = XmlReader.Create(stream)) { user = IntermediateSerializer.Deserialize(reader, null); } stream.Close(); return user; 

我会尝试使用这样的东西。

我将此属性添加到我的List类型,然后它工作了(有同样的问题):

 [System.Xml.Serialization.XmlElementAttribute("NameOfMyField")] public List NameOfMyField{get;set;} 

我认为这是你的解决方案。

它可能与enum的反序列化有关….因为它将它序列化为字符串值…可能无法为字符创建正确的枚举值。 没有测试过这个假设……