Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Wenn die ISerializable-Schnittstelle für ein Objekt implementiert wird, kann der Serialisierungsprozess angepasst werden. Dies empfiehlt sich vor allem, wenn der Wert einer Membervariablen nach der Deserialisierung ungültig ist und Sie einen Wert für die Variable bereitstellen müssen, um den Zustand des Objekts vollständig wiederherstellen zu können. Außerdem dürfen Sie bei einer Klasse keine Standardserialisierung verwenden, die mit dem Serializable-Attribut gekennzeichnet ist und für die auf Klassenebene oder für ihre Konstruktoren deklarative oder imperative Sicherheit gilt. Stattdessen müssen diese Klassen immer die ISerializable-Schnittstelle implementieren.
Die Implementierung von ISerializable umfasst auch die Implementierung der GetObjectData-Methode und eines speziellen Konstruktors, der bei der Deserialisierung des Objekts verwendet wird. Im folgenden Codebeispiel wird demonstriert, wie ISerializable für die MyObject-Klasse aus einem vorangehenden Abschnitt implementiert wird.
[Serializable]
public class MyObject : ISerializable
{
public int n1;
public int n2;
public String str;
public MyObject()
{
}
protected MyObject(SerializationInfo info, StreamingContext context)
{
n1 = info.GetInt32("i");
n2 = info.GetInt32("j");
str = info.GetString("k");
}
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter
=true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("i", n1);
info.AddValue("j", n2);
info.AddValue("k", str);
}
}
Wenn während der Serialisierung GetObjectData aufgerufen wird, müssen Sie die mit dem Methodenaufruf bereitgestellte SerializationInfo auffüllen. Fügen Sie die zu serialisierenden Variablen einfach als Name-Wert-Paare hinzu. Als Name kann ein beliebiger Text verwendet werden. Welche Membervariablen SerializationInfo hinzugefügt werden, können Sie frei entscheiden. Voraussetzung ist jedoch, dass genügend Daten serialisiert werden, um das Objekt während der Deserialisierung wiederherzustellen. Abgeleitete Klassen sollten die GetObjectData-Methode für das Basisobjekt aufrufen, wenn dieses ISerializable implementiert.
Beachten Sie, dass es durch die Serialisierung anderem Code ermöglicht werden kann, Objektinstanzdaten anzuzeigen und zu ändern, die andernfalls nicht zugänglich wären. Daher ist für Code, der Serialisierung durchführt, die SecurityPermission unter Angabe des SerializationFormatter-Flags erforderlich. Entsprechend der Standardrichtlinie bedeutet dies, dass diese Berechtigung nicht für aus dem Internet gedownloadeten Code oder Code aus einem Intranet erteilt wird. Diese Berechtigung wird nur für Code auf dem lokalen Computer erteilt. Die GetObjectData-Methode muss entweder durch Anfordern der SecurityPermission unter Angabe des SerializationFormatter-Flags oder durch Anfordern von anderen Berechtigungen, die insbesondere private Daten schützen, explizit geschützt werden.
Wenn in einem privaten Feld vertrauliche Informationen gespeichert werden, sollten Sie die entsprechenden Berechtigungen für GetObjectData anfordern, um die Daten zu schützen. Berücksichtigen Sie, dass Code, dem die SecurityPermission unter Angabe des SerializationFormatter-Flags gewährt wurde, die in privaten Feldern gespeicherten Daten anzeigen und verändern kann. Ein bösartiger Aufrufer, dem diese SecurityPermission gewährt wurde, kann Daten wie ausgeblendete Verzeichnispfade oder erteilte Berechtigungen anzeigen lassen und die Daten verwenden, um eine Sicherheitslücke auf dem Computer auszunutzen. Eine vollständige Liste der Flags für Sicherheitsberechtigungen, die Sie festlegen können, finden Sie unter SecurityPermissionFlag-Enumeration.
Sowohl GetObjectData als auch der gesonderte Konstruktor müssen implementiert werden, wenn einer Klasse ISerializable hinzugefügt wird. Der Compiler gibt eine Warnung aus, wenn GetObjectData fehlt. Wenn jedoch der Konstruktor fehlt, wird keine Warnung ausgegeben, da die Implementierung eines Konstruktors nicht erzwungen werden kann. Wenn außerdem versucht wird, eine Klasse ohne den Konstruktor zu deserialisieren, wird eine Ausnahme ausgelöst.
Der aktuelle Entwurf wurde einer SetObjectData-Methode vorgezogen, um potenzielle Sicherheits- und Versionskontrollprobleme zu umgehen. Eine SetObjectData-Methode muss beispielsweise öffentlich sein, wenn sie als Teil einer Schnittstelle definiert wird. Die Benutzer müssen demnach Code schreiben, um zu verhindern, dass die SetObjectData-Methode mehrfach aufgerufen wird. Andernfalls kann eine bösartige Anwendung, die die SetObjectData-Methode für ein Objekt während der Ausführung einer Operation aufruft, mögliche Probleme verursachen.
Während der Deserialisierung wird SerializationInfo an die Klasse übergeben, die den für diesen Zweck bereitgestellten Konstruktor verwendet. Die für den Konstruktor geltenden Sichtbarkeitseinschränkungen werden bei der Deserialisierung des Objekts ignoriert, d. h., Sie können die Klasse als öffentlich, geschützt, intern oder privat markieren. Der Konstruktor sollte jedoch als geschützt markiert werden, sofern die Klasse nicht versiegelt ist. Ist dies der Fall, sollte der Konstruktor als privat markiert werden. Der Konstruktor sollte außerdem eine eingehende Überprüfung von Eingaben durchführen. Um Missbrauch durch bösartigen Code zu verhindern, muss der Konstruktor dieselben Sicherheitsüberprüfungen und Berechtigungen erzwingen, die zum Abrufen einer Instanz der Klasse durch einen anderen Konstruktor erforderlich sind. Wenn Sie diese Empfehlung nicht umsetzen, kann bösartiger Code ein Objekt im Voraus serialisieren, mit der SecurityPermission unter Angabe des SerializationFormatter-Flags die Steuerung übernehmen und das Objekt auf einem Clientcomputer deserialisieren, wobei alle Sicherheitseinstellungen umgangen werden, die bei einer standardmäßigen Instanzerstellung mit einem öffentlichen Konstruktor gelten.
Um den Zustand des Objekts wiederherzustellen, müssen nur die Werte der Variablen aus SerializationInfo unter Verwendung der bei der Serialisierung verwendeten Namen abgerufen werden. Wenn die Basisklasse ISerializable implementiert, sollte der Basiskonstruktor aufgerufen werden, damit das Basisobjekt seine Variablen wiederherstellen kann.
Wenn Sie von einer Klasse, die ISerializable implementiert, eine neue Klasse ableiten, muss die abgeleitete Klasse sowohl den Konstruktor als auch die GetObjectData-Methode implementieren, wenn sie über zu serialisierende Variablen verfügt. Im folgenden Codebeispiel wird dieser Vorgang unter Verwendung der bereits zuvor gezeigten MyObject-Klasse veranschaulicht.
[Serializable]
public class ObjectTwo : MyObject
{
public int num;
public ObjectTwo() : base()
{
}
protected ObjectTwo(SerializationInfo si, StreamingContext context) : base(si,context)
{
num = si.GetInt32("num");
}
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter
=true)]
public override void GetObjectData(SerializationInfo si, StreamingContext context)
{
base.GetObjectData(si,context);
si.AddValue("num", num);
}
}
Achten Sie darauf, die Basisklasse im Deserialisierungskonstruktor aufzurufen, da der Konstruktor für die Basisklasse andernfalls nicht aufgerufen wird, so dass das Objekt nach der Deserialisierung nicht vollständig erstellt wird.
Objekte werden von innen nach außen rekonstruiert, d. h., das Aufrufen von Methoden während der Deserialisierung kann unerwünschte Nebeneffekte haben, wenn sich die aufgerufenen Methoden auf Objektverweise beziehen, die zum Zeitpunkt des Aufrufs noch nicht deserialisiert worden sind. Wenn die deserialisierte Klasse IDeserilizationCallback implementiert, wird die OnDeserialization-Methode automatisch aufgerufen, sobald das gesamte Objektdiagramm deserialisiert wurde. Zu diesem Zeitpunkt sind auch die untergeordneten Objekte, auf die verwiesen wurde, vollständig wiederhergestellt. Eine Hashtabelle ist ein typisches Beispiel für eine Klasse, die ohne Verwendung des oben genannten Ereignislisteners schwer zu deserialisieren ist. Es ist einfach, die Schlüssel-Wert-Paare während der Deserialisierung abzurufen. Es kann sich jedoch problematisch gestalten, diese Objekte dann wieder der Hashtabelle hinzuzufügen, da nicht gewährleistet ist, dass die von der Hashtabelle abgeleiteten Klassen deserialisiert wurden. Daher wird davon abgeraten, zu diesem Zeitpunkt Methoden für Hashtabellen aufzurufen.
Siehe auch
Binäre Serialisierung | Zugriff auf Objekte in anderen Anwendungsdomänen mit .NET-Remoting | XML- und SOAP-Serialisierung | Sicherheit und Serialisierung | Codezugriffssicherheit