DataContractSerializer не вызывает мой конструктор?
Я только что понял что-то сумасшедшее, что я предполагал совершенно невозможным: при десериализации объекта DataContractSerializer не вызывает конструктор!
Возьмите этот класс, например:
[DataContract]
public class Book
{
public Book()
{ // breakpoint here
}
[DataMember(Order = 0)]
public string Title { get; set; }
[DataMember(Order = 1)]
public string Author { get; set; }
[DataMember(Order = 2)]
public string Summary { get; set; }
}
Когда я десериализую объект этого класса, точка останова не попадает. Я не знаю, как это возможно, поскольку это единственный конструктор для этого объекта!
Я предположил, что, возможно, дополнительный компилятор был создан компилятором из-за атрибута DataContract
, но я не смог найти его через отражение...
Итак, мне хотелось бы знать следующее: как создать экземпляр моего класса без вызова конструктора
ПРИМЕЧАНИЕ. Я знаю, что я могу использовать атрибут OnDeserializing
для инициализации моего объекта при начале десериализации, это не вопрос моего вопроса.
Ответы
Ответ 1
DataContractSerializer
(например, BinaryFormatter
) не использует конструктор any. Он создает объект как пустую память.
Например:
Type type = typeof(Customer);
object obj = System.Runtime.Serialization.
FormatterServices.GetUninitializedObject(type);
Предполагается, что процесс десериализации (или обратный вызов при необходимости) полностью инициализирует его.
Ответ 2
Есть некоторые сценарии, которые не были бы возможны без такого поведения. Подумайте о следующем:
1) У вас есть объект, у которого есть один конструктор, который устанавливает новый экземпляр в "инициализированное" состояние. Затем в этот экземпляр вызываются некоторые методы, которые приводят его в "обработанное" состояние. Вы не хотите создавать новые объекты, имеющие "обработанное" состояние, но вы все же хотите сериализовать/десериализовать экземпляр.
2) Вы создали класс с частным конструктором и некоторые статические свойства для управления небольшим набором разрешенных параметров конструктора. Теперь вы все еще можете сериализовать/десериализовать их.
XmlSerializer имеет поведение, которое вы ожидали. У меня были некоторые проблемы с XmlSerializer, потому что для этого нужен конструктор по умолчанию. В связи с этим иногда имеет смысл иметь частные сеттеры. Но XmlSerializer также нуждается в публичном getter и setter на свойствах для сериализации/десериализации.
Я думаю о поведении DataContractSerializer/BinaryFormatter, как о приостановке состояния экземпляра во время сериализации и возобновлении во время десериализации. Другими словами, экземпляры не "построены", а "восстановлены" в более раннем состоянии.
Как уже упоминалось, атрибут [OnDeserializing] позволяет синхронизировать несериализованные данные.