Вызов конструктора выполняет две вещи (или, по крайней мере, должен делать).
Один из них - выделить определенный объем памяти для объекта и выполнить все необходимые действия для того, чтобы он стал объектом для остального мира .NET (обратите внимание на определенное количество движений руки в этом объяснении).
Другой - привести объект в допустимое начальное состояние, возможно, на основе параметров - это то, что будет делать фактический код в конструкторе.
Десериализация делает то же самое, что и первый шаг, вызывая FormatterServices.GetUninitializedObject
, а затем делает то же самое, что и второй шаг, устанавливая значения для полей, эквивалентные тем, которые были записаны во время сериализации (что может потребовать десериализации других объектов, чтобы указанные значения).
Теперь состояние, в которое десериализация помещает объект, может не соответствовать возможному для любого конструктора. В лучшем случае это будет расточительно (все значения, установленные конструктором, будут перезаписаны), а в худшем - опасно (у конструктора есть побочный эффект). Это также могло быть просто невозможно (только конструктор - это тот, который принимает параметры - сериализация не имеет возможности узнать, какие аргументы использовать).
Вы можете рассматривать его как особый тип конструктора, используемый только при десериализации (пуристы ОО будут - и должны - содрогнуться при мысли о конструкторе, который не конструирует, я имею в виду это только как аналогию, если вы знаете, что С ++ думает о способ переопределения new
работает в том, что касается памяти, и у вас есть еще лучшая аналогия, хотя все еще просто аналогия).
В некоторых случаях это может быть проблемой - возможно, у нас есть readonly
поля, которые могут быть установлены только конструктором, или, может быть, у нас есть побочные эффекты, которые мы хотим.
Решение обоих - переопределить поведение сериализации с помощью ISerializable
. Это будет сериализовано на основе вызова _5 _, а затем вызовите конкретный конструктор с полями SerializationInfo
и StreamingContext
для десериализации (указанный конструктор может быть даже частным, что означает, что большая часть другого кода его даже не увидит). Следовательно, если мы можем десериализовать readonly
поля и иметь какие-либо побочные эффекты, которые нам нужны (мы также можем делать всевозможные вещи, чтобы контролировать, что и как сериализуется).
Если мы просто позаботимся о том, чтобы при десериализации произошел побочный эффект, который может произойти при построении, мы можем реализовать IDeserializationCallback
, и мы будем вызывать IDeserializationCallback.OnDeserialization
, когда десериализация завершится.
Что касается других вещей, которые делают то же самое, в .NET есть другие формы сериализации, но это все, о чем я знаю. Можно вызвать FormatterServices.GetUninitializedObject
самостоятельно, но за исключением случая, когда у вас есть строгая гарантия, что последующий код переведет созданный объект в допустимое состояние (то есть именно в той ситуации, в которой вы находитесь при десериализации объекта из данных, созданных путем сериализации того же вроде объекта) делать это чревато и является хорошим способом создать действительно трудно диагностируемую ошибку.
person
Jon Hanna
schedule
30.11.2010
new Car
был вызван только один раз. Вы можете попробовать это в двух процессах. - person leppie   schedule 17.08.2010