2009-05-20 16 views
5

我是新來的C#XmlSerializer,所以我可能會缺少一些基本的東西在這裏。XmlSerializer.Deserialize()不正確反序列化<T>

我遇到的問題是我有一個類有另一個類的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()我得到的用戶名屬性的用戶對象設置正常,但字符屬性是一個空列表:爲什麼字符屬性正確序列化到我

Username: Somebody 
Characters: 0 

任何人能解釋,但不會反序列化?

+3

你不需要[Serializable]類型。 Xml Serializer的行爲完全獨立於該屬性。 – Cheeso 2009-05-20 21:44:15

+0

好的;因爲我們(或者我至少)懷疑問題出在「真實」的代碼中(未顯示)。你在列表的「設置」訪問器中做了什麼有趣的事情?那將是我看起來的第一個地方。 – 2009-05-20 21:59:41

+0

不,它們都是基本屬性,在get或set訪問器中沒有什麼特別之處。他們都看起來有點像這樣: public T PropertyName {get;組; } – Andy 2009-05-20 22:06:54

回答

1

與代碼把玩了很長一段時間後,我終於放棄了對使用XmlSerializer的默認行爲的想法。

所有相關類現在都繼承IXmlSerializer並實現ReadXml()和WriteXml()函數。我真的希望採取懶惰的路線,但現在我已經玩過IXmlSerializer,我意識到它確實不難,而且增加的靈活性非常好。

-2

它可能與枚舉的反序列化有關......因爲它將其作爲字符串值序列化......可能無法爲該字符創建正確的枚舉值。沒有測試過這個假設...

+0

在我的實際代碼項目中,根類有其他枚舉正在被正確序列化和反序列化。 我可以序列化和反序列化字符列表中的單個對象。只有在反序列化User對象時,進程出現故障並且「字符」列表爲空,且不會引發異常。 – Andy 2009-05-20 22:11:10

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; 

我會嘗試使用類似這樣的東西。

5

無法重現;我得到(固定更直接的bug後):

Username: Somebody 
Characters: 1 

變化:

  • WriteLine,而不是WriteFormat(這使它不能編譯)
  • 初始化默認構造函數列表(這阻止CreateAndSave從工作):
    • public User() { Characters = new List<Character>(); }
    • public Character() { Skills = new List<Skill>(); }
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]); 
    } 
} 

希望有所幫助。

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))] 
0

我加入這個屬性到我的列表類型,然後它的工作(有你同樣的問題):

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

我覺得這是你的解決方案。

1

我知道這是舊的,但我有同樣的問題。

我發現的是,如果我有一個在圖中實現IXmlSerializable的對象(所以我想反序列化的主對象不會實現接口,但它中的一個對象實現它),它將所有反序列化。列表不再反序列化,既不是我正在談論的對象。序列化是完美的。

相關問題