简体   繁体   English

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

[英]XmlSerializer.Deserialize() isn't deserializing a List<T> correctly

I am new to the C# XmlSerializer so I might be missing something basic here. 我是C#XmlSerializer的新手,所以我可能会遗漏一些基本的东西。

The problem I am running into is that I have one class that has a List<T> of another class. 我遇到的问题是我有一个类有另一个类的List<T> When I serialize the main class the XML looks beautiful and all the data is intact. 当我序列化主类时,XML看起来很漂亮,所有数据都完好无损。 When I deserialize the XML, the data in the List<T> disappears and I am left with an empty List<T> . 当我反序列化XML时, List<T>的数据消失了,我留下了一个空的List<T> I am not receiving any errors and the serialization portion works like charm. 我没有收到任何错误,序列化部分就像魅力一样。

What am I missing with the deserialization process? 反序列化过程中我错过了什么?

EDIT: Note that the code shown below does not reproduce the problem - it works. 编辑:请注意,下面显示的代码不会重现问题 - 它的工作原理。 This was a simplified version of the real code, which did not work. 这是真正的代码, 没有工作的简化版本。 Unfortunately, the code below was simplified enough to not reproduce the problem! 不幸的是,下面的代码已经足够简化,无法重现问题!

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

The XML generated by executing CreateAndSave() looks like so: 通过执行CreateAndSave()生成的XML如下所示:

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

Perfect! 完善! That's the way it should look. 这就是应该看的样子。 If I then execute RestoreAndPrint() I get a User object with the Username property set properly but the Characters property is an empty list: 如果我然后执行RestoreAndPrint()我得到一个User对象,其Username属性设置正确但Characters属性是一个空列表:

Username: Somebody
Characters: 0

Can anybody explain to me why the Characters property is serialized properly but won't deserialize? 任何人都可以向我解释为什么Characters属性被正确序列化但不会反序列化?

Cannot reproduce; 无法重现; I get (after fixing the more immediate bugs): 我得到(在修复更直接的错误之后):

Username: Somebody
Characters: 1

Changes: 变化:

  • WriteLine instead of WriteFormat (which prevented it compiling) WriteLine而不是WriteFormat (阻止它编译)
  • init the lists in the default constructors (which prevented CreateAndSave from working): 初始化默认构造函数中的列表(阻止CreateAndSave工作):
    • public User() { Characters = new List<Character>(); }
    • public Character() { Skills = new List<Skill>(); }

In the past, when serializing lists, I've used the [XmlArray] and [XmlArrayItem] annotations. 过去,在序列化列表时,我使用了[XmlArray]和[XmlArrayItem]注释。 You would then put an [XmlIgnore] annotation on the Characters property. 然后,您将在Characters属性上放置一个[XmlIgnore]注释。 In your case, it would look something like this: 在你的情况下,它看起来像这样:

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

Hope that helps. 希望有所帮助。

I know this is old but i have the same problem. 我知道这是旧的,但我有同样的问题。

What i found is that if i have an object that implements IXmlSerializable in the graph (so the main object that i want to deserialize dosen't implement the interface, but an object in it implements it), it ruins all the deserialization. 我发现如果我有一个在图中实现IXmlSerializable的对象(所以我想反序列化的主要对象不实现接口,但是它中的一个对象实现它),它会破坏所有的反序列化。 Lists don't deserialize anymore, neither the object i'm talking about. 列表不再反序列化,也不是我正在谈论的对象。 Serialization works perfect. 序列化工作完美。

Perhaps, instead of a StreamReader, create an XmlReader, instead. 也许,而不是StreamReader,而是创建一个XmlReader。 Also, as a troubleshooting step, you might try your existing code with explicit types (as below) instead of "var" declarations. 此外,作为故障排除步骤,您可以尝试使用显式类型(如下所示)而不是“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;
}

EDIT: Also, try the XmlInclude annotation on your User class. 编辑:此外,尝试在您的User类上的XmlInclude批注。

[XmlInclude( typeof( Character ) )]

After futzing around with the code for a long time I finally gave up on the idea of using the default behaviour of the XmlSerializer. 在对代码进行了很长时间的讨论之后,我终于放弃了使用XmlSerializer的默认行为的想法。

All of the relevant classes now inherit IXmlSerializer and implement the ReadXml() and WriteXml() functions. 所有相关类现在都继承IXmlSerializer并实现ReadXml()和WriteXml()函数。 I was really hoping to take the lazy route but now that I've played with IXmlSerializer I realize that it really isn't difficult at all and the added flexibility is really nice. 我真的希望采取懒惰的路线,但现在我已经玩过IXmlSerializer,我意识到它真的不难,增加的灵活性非常好。

I added this attribute to my List types and it worked then (had your same problem): 我将此属性添加到我的List类型,然后它工作了(有同样的问题):

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

I think this is your solution. 我认为这是你的解决方案。

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;

I would try using something like this. 我会尝试使用这样的东西。

It might have to do with the deserializing of the enum....since it serialized it as the string value...might have trouble creating the correct enum value for the character. 它可能与enum的反序列化有关....因为它将它序列化为字符串值...可能无法为字符创建正确的枚举值。 Have not tested this hypothesis... 没有测试过这个假设......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 XmlSerializer.Deserialize List &lt;&gt;项目 - XmlSerializer.Deserialize on a List<> item XmlSerializer.Deserialize即使使用XmlInclude也不能与基类一起使用 - XmlSerializer.Deserialize doesn't work with the base class even with XmlInclude 反序列化 XML 文件使用 XmlSerializer.Deserialize 从 MemoryStream 不起作用 - Deserializing XML File using XmlSerializer.Deserialize from MemoryStream not working 反序列化大型XML文档中的单个元素:由于名称空间问题,xmlSerializer.Deserialize(xmlReader.ReadSubtree())失败 - Deserializing a single element in a large XML document: xmlSerializer.Deserialize(xmlReader.ReadSubtree()) fails due to namespace issues 使用C#中的XmlSerializer.Deserialize()反序列化父命名空间之外的子节点 - Deserializing child nodes outside of parent's namespace using XmlSerializer.Deserialize() in C# 无法使用XmlSerializer反序列化对象列表 - Can't deserialize list of objects with XmlSerializer XmlSerializer.Deserialize() 似乎不起作用 - XmlSerializer.Deserialize() Does not appear to work XmlSerializer.Deserialize忽略不必要的元素 - XmlSerializer.Deserialize ignore unnecessary elements XmlSerializer.Deserialize为子类(不是数组) - XmlSerializer.Deserialize for a sub class (not an array) 来自Socket c#的XmlSerializer.Deserialize() - XmlSerializer.Deserialize() from Socket c#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM