Как я могу вызвать конструктор перед десериализацией?

Я пытаюсь сериализовать и десериализовать пользовательский класс с помощью сериализации контракта данных. Сериализация работает отлично. Однако при десериализации у меня возникает проблема из-за этого (источник):

Конструкторы не вызываются при десериализации объектов.

Дело в том, что я делаю небольшую инициализацию в конструкторе. Это включает в себя некоторые структуры данных.

Без вызова конструктора структуры данных будут null, а вызовы функций установки во время десериализации завершатся ошибкой.

Как я могу вызвать конструктор или инициализировать объект до или во время процесса десериализации, прежде чем будет использован какой-либо метод доступа?

Есть несколько методов, которые я могу объявить как обратные вызовы через атрибуты, например этот (тот же источник):

// This method is called after the object 
// is completely deserialized. Use it instead of the
// constructror.
[OnDeserialized] 
void OnDeserialized(StreamingContext context)
{
    fullName = firstName + " " + lastName;
}

Но похоже, что все они запускаются после десериализации.

Нужно ли переходить на XML-сериализацию?


person null    schedule 07.01.2016    source источник
comment
Это уже должно было произойти до того, как вы сериализовали объект. Так что делать это снова было бы неправильно.   -  person Hans Passant    schedule 07.01.2016
comment
Да, используйте метод OnDeserialized, где вы можете инициализировать свои поля. Ничто не могло получить доступ к полям/свойствам до этого.   -  person Sriram Sakthivel    schedule 07.01.2016
comment
@HansPassant десериализация происходит независимо. В ходе выполнения программы я загружаю только сериализованные данные и хочу десериализовать их в объект. Сериализация даже не происходит до десериализации (в этом экземпляре программы). Я не совсем уверен, как бы я назвал конструктор до этого.   -  person null    schedule 07.01.2016
comment
@SriramSakthivel это неправильно. Опять же, в комментариях говорится, что это происходит после десериализации, и мои результаты согласуются с этим: методы доступа используются до вызова функции. Я не могу использовать его для инициализации полей.   -  person null    schedule 07.01.2016


Ответы (1)


Создайте конструктор с подписью

protected YourClassName(SerializationInfo info, StreamingContext context)
{
}

и пусть ваш класс реализует ISerializable. При сериализации он вызывает ISerializable.GetObjectData(), при десериализации вызывает указанный выше конструктор.

См. раздел Пользовательская сериализация: реализация интерфейса ISerializable в MSDN

Если вам на самом деле не нужно выполнять работу в конструкторе, вы можете использовать атрибут [OnDeserializing] вместо [OnDeserialized], чтобы выполнить работу до десериализации, а не после.

[OnDeserializing]
private void SetValuesOnDeserializing(StreamingContext context)
{
    // Code not shown.
}

Примечание. Если в графе объектов имеется более одного метода [OnDeserializing], порядок их вызова не является дертимистическим.

person Scott Chamberlain    schedule 07.01.2016
comment
Документация лжет, когда говорит, что Любой заданный тип не может поддерживать ни одну, одну или несколько технологий сериализации., потому что я не могу одновременно реализовать ISerializable и использовать DataContractAttribute. [OnDeserializing] с другой стороны отлично работает. Спасибо - person null; 07.01.2016