Es gibt zwei Dinge, die einen Konstruktor aufrufen (oder zumindest tun sollten).
Eine ist es, eine bestimmte Menge an Speicher für das Objekt zur Seite zu legen und alle notwendigen Operationen auszuführen, um ein Objekt für den Rest der .NET-Welt zu sein (beachten Sie eine gewisse Menge an Handwaving in dieser Erklärung).
Die andere ist, das Objekt in einen gültigen Anfangszustand zu bringen, vielleicht basierend auf Parametern - das ist der eigentliche Code im Konstruktor.
Die Deserialisierung macht ähnlich wie der erste Schritt FormatterServices.GetUninitializedObject
und führt dann ähnlich wie der zweite Schritt die Werte für Felder so aus, dass sie denen entsprechen, die während der Serialisierung aufgezeichnet wurden (was eine Deserialisierung erforderlich machen kann) andere Objekte zu sagen, Werte).
Der Zustand, in dem die Deserialisierung das Objekt platziert, entspricht möglicherweise nicht dem von einem Konstruktor möglichen Status. Im besten Fall wird es verschwenderisch (alle vom Konstruktor gesetzten Werte werden überschrieben) und im schlimmsten Fall kann es gefährlich sein (Konstruktor hat einen Nebeneffekt). Es könnte auch einfach unmöglich sein (nur Konstruktor ist derjenige, der Parameter nimmt - Serialisierung hat keine Möglichkeit zu wissen, welche Argumente zu verwenden sind).
Man könnte es als eine spezielle Art von Konstruktor betrachten, der nur durch Deserialisierung verwendet wird (OO-Puristen werden - und sollten - bei der Idee eines Konstruktors, der nicht konstruiert, ich meine das nur als Analogie, wenn du das schaust weiß C++, denke an die Art und Weise, wie das Überschreiben new
funktioniert so weit wie Speicher geht und Sie haben eine noch bessere Analogie, obwohl immer noch nur eine Analogie).
Nun, das ist ein Problem in einigen Fällen sein kann - vielleicht haben wir readonly
Felder, die nur durch einen Konstruktor festgelegt werden kann, oder vielleicht haben wir Nebenwirkungen, dass wir passieren wollen.
Eine Lösung für beide besteht darin, das Serialisierungsverhalten mit ISerializable
zu überschreiben. Dies wird serialisieren basierend auf einem Aufruf an ISerializable.GetObjectData
und rufen Sie dann einen bestimmten Konstruktor mit SerializationInfo
und StreamingContext
Felder zu deserialise (der Konstruktor kann auch privat sein - was bedeutet, die meisten anderen Code wird es nicht einmal sehen). Also, wenn wir readonly
Felder deserialisieren können und irgendwelche Nebenwirkungen haben, die wir wollen (wir können auch alle möglichen Dinge tun, um zu kontrollieren, was serialisiert ist und wie).
Wenn wir nur sicherstellen wollen, dass bei der Deserialisierung einige Nebeneffekte auftreten, die beim Bau auftreten, können wir IDeserializationCallback
implementieren und wir werden IDeserializationCallback.OnDeserialization
aufgerufen haben, wenn die Deserialisierung abgeschlossen ist.
Für andere Dinge, die das gleiche tun, gibt es andere Formen der Serialisierung in .NET, aber das ist alles, was ich weiß. Es ist möglich, FormatterServices.GetUninitializedObject
selbst aufzurufen, aber ohne einen Fall, in dem Sie sicher sind, dass der nachfolgende Code das erzeugte Objekt in einen gültigen Zustand versetzt (genau die Situation, in der Sie ein Objekt aus Serialisierungsdaten deserialisieren) Art von Objekt) ist so ein Problem und eine gute Möglichkeit, einen wirklich schwer zu diagnostizierenden Fehler zu produzieren.
Gute Frage. Um dies zu umgehen, müssen Sie während der Deserialisierung einige Pointer-/Referenzkorrekturen durchführen, was schwierig oder sogar unmöglich sein kann. Beachten Sie, dass 'New Car' nur einmal aufgerufen wurde. Sie können dies in 2 Prozessen versuchen. – leppie
möglich Duplikat von [DataContractSerializer ruft nicht meinen Konstruktor auf?] (Http://stackoverflow.com/questions/1076730/datacontractserrializer-doesnt-call-my-constructor) –
Hinweis: Die andere Frage, die ich verknüpfte, ist über DataContractSerializer , aber die Erklärung ist das gleiche für BinaryFormatter –