2009-11-10 14 views
11

Mam strukturę tak:serializacji XML .NET i dziedziczenie

public interface A 
{ 
    public void method(); 
} 

public class B : A 
{ 
} 

public class C : A 
{ 
} 

List<A> list; 

lista zawiera obiekty typu B i C mają też kilka pól, które chciałbym zachować, mogę teraz szeregować je, deserializowania powrotem i uzyskać odpowiednie instancje obiektu? Korzystnie do XML

EDIT:

Czy jest jakiś prosty sposób na serializacji tej listy, która zawiera interfejsy, a następnie z powrotem do nieseryjny przypadkach B i C?

Odpowiedz

4

Masz y spróbuj uż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

Tak, ale musisz grać z atrybutami XmlElement, XmlRoot i XmlArray. Każdy typ wymaga nazwy własnego elementu.

EDYCJA: Niektóre przykładowy kod. Wszystkie klasy pochodzą od wspólnej klasy bazowej.

Oto przykładowy kod:

[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: Usuń serializacji atrybutu, ponieważ nie jest potrzebne (ale jest potrzebna w moim projekcie, gdzie kod jest od)

+1

Nie potrzebujesz '[Serializable]'. Nie jest używany przez szeregowanie XML. –

6

Zakładając, że używasz wbudowanego w .net serializacji XML należy zapoznać się z poniższym atrybut:

System.Xml.Serialization.XmlIncludeAttribute 

To pozwala na powierzeniu serializatora na inne rodzaje gdy szeregowania/de serializowanie.

Dodawanie nowych typów do listy i brak aktualizacji danych metadanych seryjnych jest częstym źródłem pomyłek, upewnij się, że masz wystarczający zasięg testu.

0

Twoim przypadku dokonać abstrakcyjnej klasy, która implementuje interfejs jak:

abstract class Abs : A 

a następnie czerpać swoje zajęcia z ABS

public class B : Abs 
public class C : Abs 

i LIST;

teraz użyj XmlIncludeAttribute, aby dodać swoje typy do tablicy typów XmlSerializer.

5

Używałbym klasy abstrakcyjnej zamiast interfejsu (ponieważ nie można serializować typu interfejsu), wtedy zamiast twardego kodowania typu przy użyciu atrybutu XmlInclude dodałabym znane typy do XmlSerializer w Serial i Deserializacji metod takich jak:

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 nie działa z interfejsami.Więc można:

interfejs Konwersja do klasy abstrakcyjnej, a następnie użyć XmlIncludeAttribute dla niego lub dostarczyć KnownTypes do XmlSerializer

lub

Wdrożenie IXmlSerializable dla typu macierzystego

lub

Należy rozważyć użycie DataContractSerializer z .NET 3.0

Powiązane problemy