Serialisierung
Hinweis
Diese Inhalte wurden mit Genehmigung von Pearson Education, Inc. aus Framework Design Guidelines nachgedruckt: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition. Diese Ausgabe wurde 2008 veröffentlicht, und das Buch wurde seitdem in der dritten Ausgabe vollständig überarbeitet. Einige der Informationen auf dieser Seite sind möglicherweise veraltet.
Unter Serialisierung wird das Konvertieren des Zustands eines Objekts in ein Format verstanden, das leicht persistent gespeichert oder transportiert werden kann. Beispielsweise können Sie ein Objekt serialisieren, es mit HTTP über das Internet transportieren und auf dem Zielcomputer deserialisieren.
.NET Framework bietet drei wichtige Serialisierungstechnologien, die für verschiedene Serialisierungsszenarien optimiert wurden. In der folgenden Tabelle werden diese Technologien und die zugehörigen Framework-Haupttypen für die jeweilige Technologie beschrieben.
Technologiename | Haupttypen | Szenarios |
---|---|---|
Datenvertragsserialisierung | DataContractAttribute DataMemberAttribute DataContractSerializer NetDataContractSerializer DataContractJsonSerializer ISerializable |
Allgemeine Persistenz Webdienste JSON |
XML-Serialisierung | XmlSerializer | XML-Format mit vollständiger Kontrolle über die Form des XML-Codes |
Laufzeitserialisierung (binär und SOAP) | SerializableAttribute ISerializable BinaryFormatter SoapFormatter |
.NET-Remotezugriff |
✔️ DENKEN Sie beim Entwurf neuer Typen auch an eine mögliche Serialisierung.
Auswählen einer geeigneten Serialisierungstechnologie, die unterstützt werden soll
✔️ ERWÄGEN Sie Unterstützung von Datenvertragsserialisierung, wenn Instanzen Ihres Typs möglicherweise in Webdiensten verwendet oder beibehalten werden müssen.
✔️ ERWÄGEN Sie Unterstützung von XML-Serialisierung anstelle von oder zusätzlich zu Datenvertragsserialisierung, wenn Sie eine größere Kontrolle über das bei der Serialisierung des Typs erstellte XML-Format benötigen.
Dies kann in einigen Interoperabilitätsszenarien von Bedeutung sein, wenn ein XML-Konstrukt verwendet werden muss, das von der Datenvertragsserialisierung nicht unterstützt wird, beispielsweise um XML-Attribute zu generieren.
✔️ ERWÄGEN Sie Unterstützung der Laufzeitserialisierung, wenn Instanzen des Typs über .NET-Remotegrenzen übertragen werden müssen.
❌ VERMEIDEN Sie Unterstützung der Laufzeitserialisierung oder der XML-Serialisierung, wenn diese Unterstützung lediglich aus allgemeinen Persistenzgründen implementiert wird. In solchen Fällen sollten Sie Datenvertragsserialisierung bevorzugen.
Unterstützen der Datenvertragsserialisierung
Um die Datenvertragsserialisierung für einen Typ zu unterstützen, wenden Sie DataContractAttribute auf den Typ und DataMemberAttribute auf die Member (Felder und Eigenschaften) des Typs an.
✔️ ERWÄGEN Sie, die Datenmember des Typs als öffentlich zu kennzeichnen, wenn der Typ bei teilweiser Vertrauenswürdigkeit verwendet werden kann.
Bei voller Vertrauenswürdigkeit können Datenvertragsserialisierungsprogramme nicht öffentliche Typen und Member serialisieren und deserialisieren, bei teilweiser Vertrauenswürdigkeit hingegen können ausschließlich öffentliche Member serialisiert und deserialisiert werden.
✔️ IMPLEMENTIEREN Sie einen Getter und einen Setter für alle Eigenschaften, die über ein DataMemberAttribute verfügen. Datenvertragsserialisierungsprogramme verlangen sowohl einen Getter als auch einen Setter, damit der Typ als serialisierbar betrachtet wird. (In .NET Framework 3.5 SP1 können einige Sammlungseigenschaften nur „get-only“ sein.) Wenn der Typ nicht bei teilweiser Vertrauenswürdigkeit verwendet wird, können einer oder beide Eigenschaftenaccessoren nicht öffentlich sein.
✔️ ERWÄGEN Sie die Verwendung von Serialisierungsrückrufen für die Initialisierung deserialisierter Instanzen.
Konstruktoren werden beim Deserialisieren von Objekten nicht aufgerufen. (Es gibt jedoch Ausnahmen. Konstruktoren von Sammlungen, die mit CollectionDataContractAttribute gekennzeichnet sind, werden während der Deserialisierung aufgerufen.) Daher muss jede Logik, die während der normalen Erstellung ausgeführt wird, als einer der Serialisierungsrückrufe implementiert werden.
OnDeserializedAttribute
ist das am häufigsten verwendete Rückrufattribut. Weitere Attribute in der Familie sind OnDeserializingAttribute, OnSerializingAttribute und OnSerializedAttribute. Mit ihnen können Rückrufe gekennzeichnet werden, die entsprechend vor der Deserialisierung, vor der Serialisierung oder nach der Serialisierung ausgeführt werden.
✔️ ERWÄGEN Sie die Verwendung von KnownTypeAttribute, um konkrete Typen anzugeben, die beim Deserialisieren eines komplexen Objektdiagramms verwendet werden sollen.
✔️ BERÜCKSICHTIGEN Sie die Abwärts- und Aufwärtskompatibilität, wenn Sie serialisierbare Typen erstellen oder ändern.
Beachten Sie, dass serialisierte Streams von zukünftigen Versionen des Typs in die aktuelle Version des Typs deserialisiert werden können und umgekehrt.
Berücksichtigen Sie bei allen Überlegungen, dass Datenmember, auch private und interne, ihren Namen, ihren Typ und die Reihenfolge in zukünftigen Versionen des Typs nicht mehr ändern können, es sei denn, es wird besonders darauf geachtet, dass der Vertrag erhalten bleibt, indem explizite Parameter für die Datenvertragsattribute verwendet werden.
Testen Sie die Kompatibilität der Serialisierung, wenn Sie Änderungen an den serialisierbaren Typen vornehmen. Versuchen Sie eine Deserialisierung der neuen Version in eine alte Version und umgekehrt.
✔️ ERWÄGEN Sie die Implementierung von IExtensibleDataObject, um wiederholte Umwandlungen zwischen verschiedenen Versionen des Typs zu gestatten.
Über die Schnittstelle kann das Serialisierungsprogramm sicherstellen, dass bei der wiederholten Umwandlung keine Daten verloren gehen. Die IExtensibleDataObject.ExtensionData-Eigenschaft wird zum Speichern von Daten aus der zukünftigen Version des Typs verwendet, der in der aktuellen Version unbekannt ist, und kann daher nicht in ihren Datenmembern gespeichert werden. Wenn die aktuelle Version anschließend serialisiert und in eine zukünftige Version deserialisiert wird, sind die zusätzlichen Daten im serialisierten Stream verfügbar.
Unterstützen der XML-Serialisierung
Die Datenvertragsserialisierung ist die primäre Serialisierungstechnologie (Standardserialisierung) in .NET Framework. Es gibt jedoch einige Serialisierungsszenarien, die von der Datenvertragsserialisierung nicht unterstützt werden. Beispielsweise kann die Form des vom Serialisierungsprogramm erzeugten bzw. verarbeiteten XML nicht vollständig kontrolliert werden. Wenn eine präzise Kontrolle erforderlich ist, muss XML-Serialisierung verwendet werden, und der Entwurf der Typen muss eine Unterstützung dieser Serialisierungstechnologie enthalten.
❌ VERMEIDEN Sie es, Typen speziell für die XML-Serialisierung zu entwerfen, sofern es keinen eindeutigen Grund gibt, die Form des erzeugten XML zu kontrollieren. Diese Serialisierungstechnologie wurde durch die im vorherigen Abschnitt behandelte Datenvertragsserialisierung abgelöst.
✔️ ERWÄGEN Sie eine Implementierung der IXmlSerializable-Schnittstelle, wenn Sie eine noch präzisere Kontrolle über die Form des serialisierten XML erreichen möchten, als mit den XML-Serialisierungsattributen möglich ist. Die beiden Methoden ReadXml und WriteXml der Schnittstelle erlauben eine vollständige Kontrolle des serialisierten XML-Streams. Sie können auch das XML-Schema kontrollieren, das für den Typ generiert wird, indem Sie XmlSchemaProviderAttribute
anwenden.
Unterstützen der Laufzeitserialisierung
Laufzeitserialisierung ist eine von .NET-Remotezugriff verwendete Technologie. Wenn eine Übertragung der Typen mit .NET-Remotezugriff vorgesehen ist, müssen Sie gewährleisten, dass die Typen die Laufzeitserialisierung unterstützen.
Eine grundlegende Unterstützung von Laufzeitserialisierung kann durch Anwenden von SerializableAttribute bereitgestellt werden. Komplexere Szenarien umfassen die Implementierung eines einfachen Laufzeitserialisierungsmusters (durch Implementieren von ISerializable und Bereitstellen eines Serialisierungskonstruktors).
✔️ ERWÄGEN Sie Unterstützung der Laufzeitserialisierung, wenn die Typen zusammen mit .NET-Remotezugriff verwendet werden sollen. Der System.AddIn-Namespace verwendet z. B. .NET-Remotezugriff, sodass alle zwischen System.AddIn
-Add-Ins ausgetauschten Typen Laufzeitserialisierung unterstützen müssen.
✔️ ERWÄGEN Sie die Implementierung des Laufzeitserialisierungsmusters, wenn Sie den Serialisierungsprozess vollständig kontrollieren möchten. Dies wäre z. B. der Fall, wenn Daten bei der Serialisierung oder Deserialisierung umgewandelt werden sollen.
Das Muster ist sehr einfach. Sie müssen lediglich die ISerializable-Schnittstelle implementieren und einen speziellen Konstruktor bereitstellen, der beim Deserialisieren des Objekts verwendet wird.
✔️ Definieren Sie den Serialisierungskonstruktor als geschützt, und stellen Sie zwei Parameter mit denselben Typen und Namen wie im hier gezeigten Beispiel bereit.
[Serializable]
public class Person : ISerializable
{
protected Person(SerializationInfo info, StreamingContext context)
{
// ...
}
}
✔️ IMPLEMENTIEREN Sie die ISerializable-Member explizit.
✔️ WENDEN Sie einen Linkaufruf auf die ISerializable.GetObjectData-Implementierung an. Dadurch wird gewährleistet, dass ausschließlich vollständig vertrauenswürdige Kernkomponenten und das Laufzeitserialisierungsprogramm Zugriff auf den Member haben.
Teile ©2005, 2009 Microsoft Corporation. Alle Rechte vorbehalten.
Nachdruck mit Genehmigung von Pearson Education, Inc aus Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition von Krzysztof Cwalina und Brad Abrams, veröffentlicht am 22. Oktober 2008 durch Addison-Wesley Professional als Teil der Microsoft Windows Development Series.