2009-11-10 17 views
11

ho struttura come questa:NET serializzazione XML e l'eredità

public interface A 
{ 
    public void method(); 
} 

public class B : A 
{ 
} 

public class C : A 
{ 
} 

List<A> list; 

elenco contiene oggetti di tipo B e C hanno anche alcuni campi che vorrei tenere, ora posso io serializzare, deserializzare indietro e ottenere le istanze degli oggetti corretti? Preferibilmente a XML

EDIT:

C'è un modo semplice per serializzare questo elenco che contiene le interfacce, e quindi deserializzare di nuovo a casi B e C?

risposta

4

Si ma y provare a utilizzare 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

Sì, ma è necessario giocare con gli attributi XmlElement, XmlRoot e XmlArray. Ogni tipo ha bisogno del proprio nome di elemento.

MODIFICA: alcuni esempi di codice. Tutte le classi derivano da una classe base comune.

Ecco un esempio di codice:

[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: Rimuovere serializzazione attributo come non è necessaria (ma è necessaria nel mio progetto in cui il codice è da)

+1

Non è necessario '[Serializable]'. Non è utilizzato dalla serializzazione XML. –

6

Supponendo che si sta utilizzando il built NET serializzazione XML si dovrebbe dare un'occhiata al seguente attributo: si

System.Xml.Serialization.XmlIncludeAttribute 

permette di istruire il serializzatore per includere altri tipi durante la serializzazione/de serializzazione.

L'aggiunta di nuovi tipi all'elenco e il mancato aggiornamento dei metadati di serializzazione è una fonte comune di errori, assicurarsi di disporre di una copertura di test adeguata.

0

Per il vostro caso fare una classe astratta che implementa l'interfaccia come:

abstract class Abs : A 

e poi derivano le vostre classi da Abs

public class B : Abs 
public class C : Abs 

e List lista;

ora utilizzare XmlIncludeAttribute per aggiungere i tipi nell'array di tipi di XmlSerializer.

5

vorrei utilizzare una classe astratta anziché un'interfaccia (come non si può serializzare un tipo di interfaccia), allora invece di difficile codifica del tipo utilizzando l'attributo XmlInclude, vorrei aggiungere i tipi conosciuti al XmlSerializer nella serie e metodi Deserialize in questo modo:

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 non funziona con le interfacce.Così si può:

interfaccia Converti in classe astratta e quindi utilizzare XmlIncludeAttribute per esso o fornire KnownTypes per XmlSerializer

o

Implementare IXmlSerializable per il tipo di genitore

o

Considerare l'utilizzo DataContractSerializer da .NET 3.0

Problemi correlati