2015-07-11 3 views
0

В настоящее время я пытаюсь сериализовать и десериализовать некоторые из моих классов в XML. Один способ (List -> XML) отлично работает (см. Пример ниже). Другой способ не будет работать правильно. Класс, который я не хочу deserialize, содержит другой список другого класса. Это также верно в файле XML. Но когда я десериализую класс, это не сработает.XML (De) Сериализация списка

В приведенном ниже примере это означает, что класс Foo корректно сериализуется со своим списком баров. Но когда я десериализую только 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; 
     } 
    } 
} 
Смежные вопросы