Kleine Fallstricke der Serialisierung

Eine Klasse soll als Ergebnis eines guten alten ASMX basierten SOAP Web Service von einem Server an einen Client gesendet werden. Die Klasse hat neben den Eigenschaften, die den Client etwas angehen, auch noch interne Strukturen, die für die Verarbeitung genutzt werden. Diese werden geeignet markiert, etwa so:

[Serializable, XmlType("Test")] public class Item
{
[XmlAttribute("id")] public string UniqueName { get; set; }
[XmlIgnore] public Context State { get; set; }
}

Hier werden automatische Felder (auto-implemented properties) benutzt, i.e. zu den deklarierten .NET Eigenschaften UniqueName und State gibt es für den Entwickler unsichtbar zugehörige .NET Felder der Klasse. Was aber, wenn die Serveranwendung tatsächlich aus mehreren AppDomains besteht, zwischen denen Instanzen der Klasse ebenso ausgetauscht werden sollen – typisch ist ein (ASP.NET) Hosting Szenario, wobei die eigentlichen Serveralgorithmen in einer AppDomain mit kontrolliertem Lebenszyklus (etwa einem Windows Dienst) implementiert sind und eine oder mehrere andere AppDomains die Kommunikation mit dem Client regeln und etwa dynamisch bei Veränderungen nachgeladen werden (etwa durch die ASP.NET Dateiüberwachung).

Die hier verwendete SOAP Serialisierung zum Client verwendet die XML Serialisierung. Diese berücksichtigt ausschließlich öffentliche (public) .NET Eigenschaften, das Ausschließen einzelner Eigenschaften geschieht wie im Beispiel durch das XmlIgnoreAttribute. Zwischen AppDomains wird allerdings die binäre Serialisierung verwenden (Kann man das wählen? Ich habe nichts dazu gefunden.), die sich an .NET Feldern und dem NonSerializedAttribute orientiert. Konkret heißt das im Beispiel, dass zwischen AppDomains beide Eigenschaften ausgetauscht werden.

Das kann natürlich so gewollt sein, keine Frage. Aber dann wäre im Beispiel der Context auch entweder serialisierbar oder ein MarshalByRefObject. Passiert es ungewollt, so kann das je nach Situation einen empfindlichen Einfluss auf die Laufzeiten haben, da mit kleinen Instanzen eventuell sehr große angehängte Objekte stillschweigend mit serialisiert werden oder unerwartete AppDomain kreuzende Aufrufe vorgenommen werden. Leider hat Microsoft aber wohl den einfachen Weg nicht implementiert, der für event Felder prima funktioniert:

[XmlIgnore][field:NonSerialized] public Context State { get; set; }

Daher ist es notwendig, auf die automatischen Eigenschaften zu verzichten und selbst ein Feld anzulegen. Nicht tragisch, aber auch nicht elegant.

[NonSerialized] private Context m_State;
[XmlIgnore] public Context State { get { return m_State; } set { m_State = value; } }

DVB.NET hat in der Klasse SourceSelection ein weiteres Problem: hier sollen Eigenschaften, die auf Objekte verweisen, als Zeichenkette serialisiert werden, wobei diese durch eindeutige Namen der Objekte zusammengesetzt werden. Dabei kommt man leider um ISerializable und Konsorten nicht herum, wenn man die binäre Serialisierung genauso nutzen möchte wie die XML Serialisierung – egal ob explizit oder wie beschrieben implizit durch AppDomain Grenzen bedingt.

Happy Coding

Jochen

Bookmark the permalink.

Schreibe einen Kommentar