2015-07-11 102 views
0

當前我試圖序列化並反序列化一些我的類到XML。一種方式(列表 - > XML)完美工作(請參見下面的示例)。另一種方式將無法正常工作。 我想要反序列化的類包含另一個類的另一個列表。這在XML文件中也是正確的。但是當我反序列化這個類時,它將不起作用。XML(De)列表序列化

在下面的例子中,這意味着Foo類可以通過其List of Bars正確地序列化。但是,當我反序列化的XML文件只有FooString和其他屬性被正確序列化。酒吧名單每次都是空的。調試器也不會隨時進入。

有人能告訴我我做錯了什麼嗎?

在此先感謝!

主被攝體看起來像這樣:

[XmlInclude(typeof (Bar))] 
[XmlRoot(ElementName = "Foo")] 
public class Foo() : IFooInterface 
{ 
    [XmlElement("FooString")] 
    public string FooString 
    { 
     // For simplifaction auto proerty, normally with 
     // backing field 
     get; 
     set; 
    } 

    // Some other properties for the xml 
    // ... 

    // Dirty Hack to serialize the List, because an Interface could not be serialized 
    // I've already tried to remove this tag, to replace it with [XmlElement("BarList")], but nothing works 
    [XmlArray("BarList")] 
    [XmlArrayItem(ElementName = "Bar", Type = typeof(Bar))] 
    public List<Bar> XmlBarList 
    { 
     get 
     { 
      return this.BarList.Select(bar => bar as Bar).ToList(); 
     } 
     set 
     { 
      this.BarList = new ObservableCollection<IBarInterface>(value); 
     } 
    } 

    private ObservableCollection<IBarInterface> barList; 

    [XmlIgnore] 
    public ObservableCollection<IBarInterface> BarList 
    { 
     get 
     { 
      return this.barList; 
     } 
     set 
     { 
      // For simplification removed Notification Proerties 
      this.barList = value; 
     } 
    } 
} 

嵌套類看起來像這樣:

[XmlType("Bar")] 
public class Bar : IBarInterface 
{ 
    [XmlElement("BarString")] 
    public string BarString 
    { 
     get; 
     set; 
    } 

    // Some other properties for the xml 
    // ... 
} 

該(解)序列化的類的類:

public class FooBarProvider() 
{ 
    // Won't work 
    // the BarList of any Foo item is everytime 
    // empty. 
    public List<Foo> Load() 
    { 
     var reader = new StreamReader("PathToTheXml.xml"); 
     var serializer = new XmlSerializer(typeof(List<Foo>)); 
     var list = (List<Foo>)serializer.Deserialize(reader); 
    } 

    // Works 
    public void Save(List<Foo> fooList) 
    { 
     var serializer = new XmlSerializer(typeof(List<Foo>)); 
     var writer = new StreamWriter("PathToTheXml.xml"); 
     serializer.Serialize(writer, fooList); 
     writer.Close(); 
    } 
} 

這是生成的XML文件:

<ArrayOfFoo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <Foo> 
    <BarList> 
     <Bar> 
     <BarString>Hello Bar!</BarString> 
     </Bar> 
    </BarList> 
    <FooString>Hello Foo!</FooString> 
    </Foo> 
</ArrayOfFoo> 

回答

0

不要使用XmlArray。它創建了一組額外的節點。改用XmlElement。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Xml; 
using System.Xml.Serialization; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     const string FILENAME = @"c:\temp\test.xml"; 
     static void Main(string[] args) 
     { 

      ArrayOfFoo aof = new ArrayOfFoo() { 
       foo = new Foo() { 
        FooString = "Hello Foo!", 
        barList = new List<BarList>() { 
         new BarList() { 
          bar = new Bar() { 
           barString = "Hello Bar!" 
          } 
         } 
        } 
       } 
      }; 

      XmlSerializer serializer = new XmlSerializer(typeof(ArrayOfFoo)); 

      StreamWriter writer = new StreamWriter(FILENAME); 
      serializer.Serialize(writer, aof); 
      writer.Flush(); 
      writer.Close(); 
      writer.Dispose(); 

      XmlSerializer xs = new XmlSerializer(typeof(ArrayOfFoo)); 
      XmlTextReader reader = new XmlTextReader(FILENAME); 
      ArrayOfFoo newAof = (ArrayOfFoo)xs.Deserialize(reader); 
     } 
    } 
    [XmlRoot(ElementName = "ArrayOfFoo")] 
    public class ArrayOfFoo 
    { 
     [XmlElement("Foo")] 
     public Foo foo { get; set; } 
    } 

    [XmlRoot(ElementName = "Foo")] 
    public class Foo 
    { 
     [XmlElement("FooString")] 
     public string FooString { get; set; } 


     [XmlElement("BarList")] 
     public List<BarList> barList { get; set; } 

    } 


    [XmlRoot(ElementName = "BarList")] 
    public class BarList 
    { 
     [XmlElement("Bar")] 
     public Bar bar { get; set; } 
    } 


    [XmlRoot(ElementName = "Bar")] 
    public class Bar 
    { 
     [XmlElement("BarString")] 
     public string barString { get; set; } 
    } 
    [XmlRoot(ElementName = "BarString")] 
    public class BarString 
    { 
     [XmlText] 
     public string value { get; set; } 
    }​ 
} 
​ 
+0

您好,感謝您的回覆。但是這也沒有奏效。我試過了。我也嘗試刪除標籤,並讓它自動決定。但是我所做的一切 - 它不會奏效:/你有另一種方法嗎? – CodeRain

+0

更新的代碼。應該工作 – jdweng

+0

謝謝你的工作:) – CodeRain

0

哦該死的!

我看到我的錯誤。

通過我的骯髒的「黑客」序列化接口對象它將創建一個臨時對象。 XmlSerializer接受臨時對象並在那裏存儲數據。

是否有任何其他解決方案來序列化和反序列化接口?在Foo課上,我知道它是一個酒吧的例子。但是界面迫使我實現IBarInterface的列表。

Foo的接口:

public interface IFooInterface 
{ 
    ObservableCollection<IBarInterface> BarList { get; } 
} 

IFooInterface的實現:

[XmlInclude(typeof(Bar))] 
[XmlRoot(ElementName ="Foo")] 
public class Foo : IFooInterface 
{ 
    ObservableCollection<IBarInterface> barList; 

    [XmlElement(ElementName ="BarList")] 
    public ObservableCollection<Bar> XmlBarList 
    { 
     get 
     { 
      // Creates an temporary Object, so it won't work 
      return this.BarList.Select(bar => bar as Bar).ToList(); 
     } 
     set 
     { 
      this.BarList = new ObservableCollection<IBarInterface>(value); 
     } 
    } 

    // Won't work out of the box with XmlSerializer 
    // so I Ignore it 
    [XmlIgnore] 
    ObservableCollection<IBarInterface> BarList 
    { 
     get 
     { 
      return this.barList; 
     } 
     set 
     { 
      this.barList = value; 
     } 
    } 
} 

Bar的接口:

public interface IBarInterface 
{ 
    string BarString { get; } 
} 

IBarInterface實現:

[XmlRoot(ElementName ="Bar")] 
public class Bar : IBarInterface 
{ 
    string BarString; 

    [XmlElement(ElementName = "BarString")] 
    string BarString 
    { 
     get 
     { 
      return this.bar; 
     } 
     set 
     { 
      this.bar = value; 
     } 
    } 
}