2009-11-10 2 views
11

У меня есть структура, как это:.NET Сериализация XML и наследование

public interface A 
{ 
    public void method(); 
} 

public class B : A 
{ 
} 

public class C : A 
{ 
} 

List<A> list; 

Список содержит объекты типа B и C, они также имеют некоторые поля, которые я хотел бы сохранить, могу я теперь сериализовать, десериализации назад и получить соответствующие экземпляры объектов? Предпочтительно, чтобы XML

EDIT:

Есть ли простой способ сериализации этого списка, который содержит интерфейсы, а затем десериализации его обратно В и С случаями?

ответ

4

You ma y попробуйте использовать DataContractSerializer:

public interface A 
{ 
} 

public class B : A 
{ 
} 

public class C : A 
{ 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<A> list = new List<A>(new A[] { new B(), new C() }); 
     var serializer = new DataContractSerializer(
      list.GetType(), new[] { typeof(B), typeof(C) }); 

     var sb = new StringBuilder(); 
     using (var stringWriter = new StringWriter(sb)) 
     using (var writer = XmlWriter.Create(stringWriter)) 
     { 
      serializer.WriteObject(writer, list); 
     } 

     using (var stringReader = new StringReader(sb.ToString())) 
     using (var reader = XmlReader.Create(stringReader)) 
     { 
      list = (List<A>)serializer.ReadObject(reader); 
     } 

    } 
} 
4

Да, но вам нужно играть с атрибутами XmlElement, XmlRoot и XmlArray. Каждый тип нуждается в собственном имени элемента.

EDIT: Некоторые примеры кода. Все классы производятся из общего базового класса.

Вот пример кода:

[XmlRoot(ElementName="Root")] 
public sealed class SomeObject 
{ 

    private BaseObject _Object; 

    [XmlElement(Type=typeof(App.Projekte.Projekt), ElementName="Projekt")] 
    [XmlElement(Type=typeof(App.Projekte.Task), ElementName="Task")] 
    [XmlElement(Type=typeof(App.Projekte.Mitarbeiter), ElementName="Mitarbeiter")] 
    public BaseObject Object 
    { 
     get 
     { 
      return _Object; 
     } 
     set 
     { 
      _Object = value; 
     } 
    } 
} 

EDIT: Удалить сериализации атрибут, как это не требуется (но необходим в моем проекте, где код с)

+1

Вам не нужно '[Serializable]'. Он не используется XML-сериализацией. –

6

Предполагая, что вы с помощью встроенного в .net XML сериализации вы должны взглянуть на следующий атрибут:

System.Xml.Serialization.XmlIncludeAttribute 

Это позволяет инструктировать сериализатор включать другие типы при сериализации/де сериализация.

Добавление новых типов в список, а не обновление метаданных сериализации является общим источником ошибок, убедитесь, что у вас есть достаточное покрытие для тестирования.

0

В вашем случае сделать абстрактный класс, который реализует свой интерфейс, как:

abstract class Abs : A 

, а затем вывести классы из Abs

public class B : Abs 
public class C : Abs 

и списка список;

теперь использовать XmlIncludeAttribute, чтобы добавить ваши типы в массив типов XmlSerializer.

5

Я бы использовал абстрактный класс вместо интерфейса (так как нельзя сериализовать тип интерфейса), а вместо жесткого кодирования типа с использованием атрибута XmlInclude я бы добавил известные типы в XmlSerializer в Serial и методы десериализации, как так:

string listXml = Serialize<List<A>>(ListA, new Type[] { typeof(B), typeof(C) }); 

    List<IA> NewList = Deserialize<List<A>>(listXml, new Type[] { typeof(B), typeof(C) }); 

    private static T Deserialize<T>(string Xml, Type[] KnownTypes) 
    { 
     XmlSerializer xs = new XmlSerializer(typeof(T),KnownTypes); 

     StringReader sr = new StringReader(Xml); 
     return (T)xs.Deserialize(sr); 
    } 

    private static string Serialize<T>(Object obj, Type[] KnownTypes) 
    { 
     StringBuilder sb = new StringBuilder(); 
     using (StringWriter sw = new StringWriter(sb)) 
     { 
      XmlSerializer xs = new XmlSerializer(typeof(T), KnownTypes); 

      xs.Serialize(sw, obj); 
     } 
     return sb.ToString(); 
    } 
0

XmlSerializer не работает с интерфейсами.Таким образом, вы можете:

Преобразовать интерфейс для абстрактного класса, а затем использовать XmlIncludeAttribute для него или предоставить KnownTypes в XmlSerializer

или

Реализовать IXmlSerializable для родительского типа

или

Рассмотрите возможность использования DataContractSerializer от .NET 3.0

Смежные вопросы