Laden...

XML Serialisierung mit Vererbung

Erstellt von Stu42 vor 16 Jahren Letzter Beitrag vor 16 Jahren 6.290 Views
S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 16 Jahren
XML Serialisierung mit Vererbung

Hallo,

also das mit dem XML Serialisierer und den Attributen ist so eine Sache. Denn wenn sich ein Attribut nicht Serialisieren lässt, gibt es bei dir Initailiserung des Serializers eine InvalidOperationException.

also hier:


XmlSerializer serializer = new XmlSerializer(typeof(Page));

Ich habe folgendes Problem. Ich habe eine List von einer Basisklasse. Wenn ich in diese Liste nun Vererbte elemente einfüge, dann kann ich diese Liste nicht mehr Serialisieren, und ich bekomme eine Exception bei:

serializer.Serialize(fs, this);

Meine abgeleitetn Klassen habe ich auch alle mit diesen XML-Serialisierung tags versehen.

Nun meine Frage:
Muss man etwas bei der XML-Serialisierung beachten, wenn man eine "Basisliste" hat, wo aber Vererbte Items drin sind?

Gruß Stu

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo Stu42,

ich vermute mal, mit "Attribute" meinst du eigentlich "Properties", oder? Attribute sind nämlich unter C# was anderes.

nd ich bekomme eine Exception bei:

Welche? Genaue Exception(meldung) immer mit angeben.

herbivore

0
767 Beiträge seit 2005
vor 16 Jahren

du musst beim erstellen des serializers die vererbten typen dem serializer bekannt geben.

entweder mit XmlInclude (Attribute auf den Properties) oder über den Constructor.


// angenommen sowas willst du serialisieren:
public abstract class MyBase
{
  //...
}

public class DerivatA : MyBase
{
  // ...
}

public class DerivatB : MyBase
{
  // ...
}

// dann entweder hier mit XmlInclude() - kann sein dass das auch aufs property gehört anstatt auf die klasse, habs nicht getested.
[XmlInclude(typeof(DerivateB))]
[XmlInclude(typeof(DerivateB))]
public class SomeData
{
  public MyBase item; // h
}

// oder beim constructor:
XmlSerializer ser = new XmlSerializer(typeof(SomeData), new Type[]{ typeof(DerivateA), typeof(DerivateB) });

so in der Art...

loop:
btst #6,$bfe001
bne.s loop
rts

S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 16 Jahren

ja genau Properties.... also diese set und get dinger....

Also bei der Methode "Serialize" bekomme ich auch eine "InvalidOperationException".

Wenn etwas mit dem zu serialisieren typ nicht stimmt, bekomme ich die Exception schon bei der Erzeugung der Klasse, und nicht erst bei dem aufruf der Methode Serialize.

In den Abgeleiteten Klassen gibt es natürlich auch Propertiers die ich nicht speicher kann (z.b. Pen´s oder Brush´es) , diese ignoriere ich aber alle Mittels [XmlIgnore()].

Das ist auch schon so , das ich in der "Basisliste" Elemente einfüge, der 5 mal oder mehr vererbt wurden.

3.971 Beiträge seit 2006
vor 16 Jahren

@ 0815Coder

Dann muss doch aber auch in den Basisklassen, das Attribut [Serializable] angegeben.

Außerdem bekommst du beim Aufrufen des Konstruktors

Orginal von 0815Coder

  
// oder beim constructor:  
XmlSerializer ser = new XmlSerializer(typeof(SomeData), new Type[]{ typeof(DerivateA), typeof(DerivateB) });  
  

ein Performance Problem. Denn bei jedem Aufruf des Konstruktors wird eine neue Assembly generiert und eingebunden. Diese wird aber nicht beim Aufruf des Destruktors wieder entladen.

Ich würde einfach in der Klasse SomeData die Schnittstelle IXmlSerializable einbinden


public class SomeData : IXmlSerializable
{
		public System.Xml.Schema.XmlSchema GetSchema()
		{
			return null;
		}

		public void ReadXml(XmlReader reader)
		{
			...
		}

		public void WriteXml(XmlWriter writer)
		{
			...
		}

		#endregion
}

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo kleines_eichhoernchen,

Dann muss doch aber auch in den Basisklassen, das Attribut [Serializable] angegeben.

ich dachte immer [Serializable] wäre nur für die binäre Serialisierung nötig, aber ich bin mir da immer nicht so sicher, weil ich XML-Serialisierung von der Arbeitsweise her sowieso quatsch finde. 🙂

herbivore

S
8.746 Beiträge seit 2005
vor 16 Jahren

Serializable ist in der Tat für die Xml-Serialisierung ohne Effekt. Das Performance-Problem läßt sich umgehen, wenn man deklarativ mittels XmlInclude arbeitet.

S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 16 Jahren

Hi,

also der Tip mit dem XmlInclude war gut, damit geht es wunderbar.

Das Performance-Problem läßt sich umgehen, wenn man deklarativ mittels XmlInclude arbeitet.

Was meinst du damit? also so wie du es geasgt hast?

z.B:

[XmlInclude(typeof(SelectableReport))]
    [XmlRoot("Report")] 
    public abstract class Base
{
 ...
}

Noch eine anderen Frage:
Lassen sich Properties auch Variable Serialisieren? Also mal speichern, und mal nicht speichern.... also über eine bedingung?

Edit:

XmlSerializer ser = new XmlSerializer(typeof(SomeData), new Type[]{ typeof(DerivateA), typeof(DerivateB) });   

Ein Typarray muss man aber nicht angeben, es reicht der Basistyp.

S
8.746 Beiträge seit 2005
vor 16 Jahren

Original von Stu42
Was meinst du damit? also so wie du es geasgt hast?

Das Problem mit der neu erzeugten Assembly entsteht nur, wenn du bestimmte Konstruktoren des XmlSerializers benutzt. Verwendest du die deklarative Methode, gibst also die Subtypen via XmlInclude an, dann kannst du den Konstruktor verwenden, der nur den Basistyp (und nicht das Typfeld) verlangt. Dieser Konstruktor führt nur einmal zur Erzeugung eines Assemblies, bringt also keine Performancenachteile mit sich.

0
767 Beiträge seit 2005
vor 16 Jahren

in den meisten fällen kann man den erzeugten XmlSerializer aber static readonly erzeugen, also auch nur einmal. dann macht das verwenden der "bösen" konstruktoren auch nichts.

loop:
btst #6,$bfe001
bne.s loop
rts