[英]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
(阻止它编译) 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.