XmlSerializer.Deserialize()没有正确地反序列化List <t> </t>

时间:2009-05-20 21:19:52

标签: c# .net xml-serialization

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

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

反序列化过程中缺少什么?

编辑:请注意,下面显示的代码无法重现问题 - 它可以正常运行。这是真实代码的简化版本,工作。不幸的是,下面的代码已经足够简化,无法重现问题!

public class User
{
  public User()
  {
    this.Characters = new List<Character>();
  }
  public string Username { get; set; }
  public List<Character> Characters { get; set; }
}

public class Character
{
  public Character()
  {
    this.Skills = new List<Skill>();
  }
  public string Name { get; set; }
  public List<Skill> 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如下所示:

<User>
  <Username>Somebody</Username>
  <Characters>
    <Character>
      <Name>Tranzor Z</Name>
      <Skills>
        <Skill>TreeClimber</Skill>
      </Skills>
    </Character>
  <Characters>
</User>

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

Username: Somebody
Characters: 0

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

8 个答案:

答案 0 :(得分:5)

无法复制;我得到(在解决了更直接的错误之后):

Username: Somebody
Characters: 1

的变化:

  • WriteLine代替WriteFormat(阻止其编译)
  • 在默认构造函数中初始化列表(阻止CreateAndSave工作):
    • public User() { Characters = new List<Character>(); }
    • public Character() { Skills = new List<Skill>(); }

答案 1 :(得分:2)

过去,在序列化列表时,我使用了[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] );
    }
}

希望有所帮助。

答案 2 :(得分:1)

或许,而不是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 ) )]

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

我知道这已经过时了,但我有同样的问题。

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

答案 5 :(得分:0)

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

return user;

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

答案 6 :(得分:0)

我将这个属性添加到我的List类型中然后它有用(有同样的问题):

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

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

答案 7 :(得分:-2)

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