2009-11-10 16 views
11

Ich habe Struktur wie folgt:.NET XML-Serialisierung, und Vererbung

public interface A 
{ 
    public void method(); 
} 

public class B : A 
{ 
} 

public class C : A 
{ 
} 

List<A> list; 

Liste enthält Objekte vom Typ B und C auch sie einige Felder, die ich halten möchte, kann ich es jetzt serialisiert, deserialisieren zurück und die richtigen Objektinstanzen bekommen? Vorzugsweise auf XML

EDIT:

Gibt es eine einfache Möglichkeit, diese Liste zu serialisiert, die Schnittstellen enthält, und es dann zu B und C Instanzen deserialisieren zurück?

Antwort

4

Sie ma y versuchen mit 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

Ja, aber Sie müssen mit den XmlElement, XmlRoot und XmlArray Attribute spielen. Jeder Typ benötigt einen eigenen Elementnamen.

EDIT: Einige Beispielcode. Alle Klassen sind von einer gemeinsamen Basisklasse abgeleitet.

Hier ist ein Beispielcode:

[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: Serialisierung Attribut entfernen, da es nicht nötig ist (ist aber in meinem Projekt benötigt, wo der Code aus ist)

+1

Sie brauchen '[Serializable]' nicht. Es wird nicht von der XML-Serialisierung verwendet. –

6

Sie mit dem integrierten Unter der Annahme, in .net XML-Serialisierung sollten Sie einen Blick auf das folgende Attribut nehmen:

System.Xml.Serialization.XmlIncludeAttribute 

Es Sie den Serializer auch auf andere Arten instruieren können, wenn die Serialisierung/de Serialisierung.

Das Hinzufügen neuer Typen zur Liste und nicht das Aktualisieren der Serialisierungsmetadaten ist eine häufige Fehlerquelle, stellen Sie sicher, dass Sie über ausreichende Testabdeckung verfügen.

0

Für Ihren Fall machen eine abstrakte Klasse, die Ihre Schnittstelle implementiert, wie:

abstract class Abs : A 

und dann leiten Sie Ihre Klassen von Abs

public class B : Abs 
public class C : Abs 

und Liste Liste;

Verwenden Sie jetzt XmlIncludeAttribute, um Ihre Typen in das Array vom Typ XmlSerializer hinzuzufügen.

5

Ich würde eine abstrakte Klasse anstelle einer Schnittstelle verwenden (wie man eine Art von Schnittstelle nicht serialisieren kann), anstatt den Typ mit dem XmlInclude-Attribut hart zu kodieren, würde ich die bekannten Typen dem XmlSerializer in der Serial hinzufügen und Deserialize Methoden wie so:

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 nicht mit Schnittstellen arbeiten.So können Sie:

Convert Schnittstelle zu abstrakten Klasse und dann XmlIncludeAttribute dafür verwenden oder liefern KnownTypes zu XmlSerializer

oder

Implementieren IXmlSerializable für den übergeordneten Typ

oder

Erwägen Sie die Verwendung DataContractSerializer von .NET 3.0