| 

.NET C# Java Javascript Exception

1
Hallo zusammen,

ich habe eine Klasse, die eine

Public Property MeineListe As New Generic.List(Of String) {"Test1", "Test2"}

hat.

Die Idee dahinter war, dass wenn das Objekt neu erstellt wird diese Werte als Standard-Werte vorgegeben werden. Wenn das Objekt jedoch deserialisiert wird, dann sollen nur die im XML vorhandenen Werte in der Liste stehen.

Was jedoch passiert: Die Werte "Test1" und "Test2" werden bei jedem Deserialisieren an die Liste angehängt.

Ich habe auch schon probiert, dies irgendwie über die Methode "New" zu steuern, was mir aber auch nicht gelungen ist. Eine Steuerung von außen ist nicht oder nur sehr unelegant lösbar.

Ich bräuchte also eine Methode, die aufgerufen wird, wenn das Objekt erstellt bzw. deserialisiert wurde, und die "weiß", ob es sich um ein deserialisiertes oder um ein neues Objekt handelt.

Ich habe es schon hiermit probiert:

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ondeserializedattribute.aspx

jedoch werden diese Methoden bei mir warum auch immer nicht aufgerufen.

Kennt jemand einen Lösungsansatz dafür?

Danke!

Benjamin
15.07.2011
Benjamin 141 1 6
4 Antworten
1
Warum verlegst Du das Instanzieren des Objektes nicht in eine "Factory" (Entwurfsmuster / Design Pattern)? Wenn kein serialisiertes Objekt vorliegt, dann instanzierst Du eins und fügst Test1 und Test2 hinzu und lieferst das zurück. Wenn jedoch eins vorliegt, dann deserialisierst Du das in der Factory und lieferst das zurück.
15.07.2011
Xantiva 2,3k 2 9
1
Die XML-Serialisierung aus System.Xml.Serialization und die Serialisierungstechnologien aus System.Runtime.Serialization haben nicht viel miteinander zu tun. Wenn Du mit dem XmlSerializer aus dem erstgenannten Namespace arbeitest, wird Dir das OnDeserialized-Attribut vermutlich nicht helfen.

Ein Ansatz wäre, mit IXmlSerializable zu arbeiten - allerdings schon eine ziemlich dicke Kanone für dieses Problem.

.NET deserialisiert ein Objekt mit einer Liste so: es ruft den Default-Konstruktor, greift anschließend über den Getter (!) auf die Liste zu und fügt die Elemente der Liste eins nach dem anderen hinzu. Deshalb greifen auch beim Deserialisieren die Defaults aus Deinem Code. (Ich bin mir nicht ganz sicher, ob das Objekt immer selbst für das Initialisieren der Liste verantwortlich ist, oder ob es selbst eine leere Liste setzt, wenn der Getter null liefert, aber das macht hier keinen Unterschied, glaube ich.)

Als Lösung neben IXmlSerializable könntest Du die Initialisierung in einen Konstruktor mit Parameter, eine Factory-Methode oder, wie von Xantiva vorgeschlagen, eine Factory verschieben. Oder Du verwendest zwei Properties: eine "normale", die einfach nur die Liste liefert, wie sie ist, und eine "MeineListeMitDefaults", die auf MeineListe delegiert, aber im Getter prüft, ob MeineListe leer ist und in diesem Fall die beiden Defaults setzt (setzt voraus, dass es gewollt ist, dass MeineListe immer diese beiden Elemente enthält und nicht nur initial). Mit dem XmlIgnore-Attribut kannst Du verhindern, dass MeineListeMitDefaults serialisiert wird. Fühlt sich für mich aber schon leicht nach Hack an, weshalb ich Dir eher die Factory(-Methode) empfehlen würde.
15.07.2011
Matthias Hlawatsch 13,2k 4 9
1
Hallo zusammen,

vielen Dakn für die vielen Rückmeldungen. Da ich die Klasse nur "intern" bearbeiten kann (also das Verhalten beim Erstellen nicht beeinflussen kann), bleibt mir wohl nur die IXmlSerializable-Variante. Mir ist hierbei ein Punkt noch nicht klar:

Muss ich dann die gesamte Klasse "manuelle" deserialisieren, oder kann ich alles automatisch lassen, und nur meine eine Property sozusagen selbst bearbeiten? Hat das schon mal jemand so gemacht?

Gruß
Benjamin
18.07.2011
Benjamin 141 1 6
0
Hallo Benjamin,

das OnDeserialized sollte schon funktionieren.
Packe die Liste in ein eigene Klasse die Du mit dem Serializable-Attribut versiehst.
In dieser Klasse packst Du Deine Liste als public Property rein.
Dort kannst du auch die OnDeserialized-Methode implementieren in der du dann ein public Property IsDeserialized setzen kannst. Dieses Property kann dann "von außen" abgefragt werden.

[OnDeserialized()]
internal void OnDeserializedMethod(StreamingContext context)
{
this.IsDeserialized = true;
}

Letztendlich serialisierst Du nicht die Liste sondern Dein eigenes Objekt mit einer enthaltenden Liste.

Gruß

CodeSniffer
15.07.2011
CodeSniffer 1,3k 4 9

Stelle deine .net-Frage jetzt!