Проверьте, соответствуют ли двоичные сериализованные данные классу, который их сериализовал.

Заголовок говорит почти то, что я хотел бы знать. У меня есть данные, которые были двоично сериализованы, и теперь я читаю их снова (имя класса остается прежним), и я хотел бы знать, пропускает ли сериализатор что-то, потому что, например, частное резервное поле могло быть переименовано.

Я сделал следующий рефакторинг:

private string descriptionField;
public string Description
{
  get { return this.descriptionField; }
}

to

public string Description { get; private set; }

Как указано в этой статьи, это не Работа. Но я действительно хотел бы знать, есть ли способ определить, не соответствует ли класс сериализованным данным.

Я не хочу сам выполнять сериализацию через реализацию ISerializable, потому что класс и его свойства довольно велики и могут быть изменены. Я бы предпочел более простое решение =)


person DerApe    schedule 22.10.2014    source источник
comment
Перехватите исключение, которое оно выдаст, но вы ничего не сможете сделать для полей, которые не были сериализованы (просто укажите значимое значение по умолчанию). Конечно, если вы реализуете ISerializable, у вас будет больше контроля над этим (вы знаете, что читаете: если одно поле не сохранено, оно не будет инициализировано, просто проверяйте перед каждым чтением).   -  person Adriano Repetti    schedule 22.10.2014
comment
Проблема в том, что он не выдает исключение, измененные имена полей просто инициализируются его значением по умолчанию.   -  person DerApe    schedule 23.10.2014
comment
Если вы переименуете что-то, оно будет выброшено, потому что старое имя переменной не может быть найдено. Ничего не произойдет, если вы что-то добавите. В этом случае они будут просто иметь значение по умолчанию. Именно здесь вы можете сделать что-то, реализующее ISerializable. В конструкторе вы вручную прочитаете поля и сможете проверить, доступны ли они в сериализованных данных. Если нет, вы их не читаете, но вы также это знаете (и это также довольно грубый способ управления версиями).   -  person Adriano Repetti    schedule 23.10.2014
comment
Как я уже сказал, в приведенном мной примере это не вызывает исключения. Неявное переименование выполняется, потому что резервное поле будет создано компилятором в фоновом режиме (я использовал BinaryFormatter). Также я не хочу использовать ISerializable, потому что класс довольно большой   -  person DerApe    schedule 23.10.2014
comment
Подумайте о OptionalFieldAttribute! Он существует, потому что BinaryFormatter может бросить в этом случае. Это просто не его поведение по умолчанию, чтобы включить его, установите BinaryFormatter.AssemblyFormat в FormatterAssemblyStyle.Full. Тем не менее, это не правильный способ управления этими вещами... ISerializable есть, даже если это довольно раздражает писать (ну, BinaryFormatter - но в целом сериализация - не правильный выбор для сохранения приложения данные между версиями, если вы не делаете довольно тривиальные вещи).   -  person Adriano Repetti    schedule 23.10.2014
comment
Когда-то мне было скучно, поэтому я создал BinaryFormatterStreamReader, который мог бы анализировать вывод BinaryFormatter в словари, чтобы я мог анализировать сериализованный контент, не имея ссылок на сериализованные типы. Вы можете использовать это только для проверки того, какой контент присутствует в потоке, чтобы убедиться, что у вас есть все. github.com/devhost/Corelicious/tree/master/Corelicious/   -  person sisve    schedule 23.10.2014


Ответы (1)


Но я действительно хотел бы знать, есть ли способ определить, не соответствует ли класс сериализованным данным?

Один из способов обнаружить это — сериализовать существующий класс с теми же данными, что и в предыдущем сериализованном файле, а затем сравнить цифровые отпечатки предыдущего и текущего сериализованных файлов.

Я не хочу сам выполнять сериализацию через реализацию ISerializable, потому что класс и его свойства довольно велики и могут быть изменены.

Поскольку вы используете BinaryFormatter и имеете дело с потенциально серьезными проблемами управления версиями, я думаю, что ваш единственный вариант — реализовать ISerializable и самостоятельно обрабатывать десериализацию, нравится вам это или нет.

person Faris Zacina    schedule 23.10.2014
comment
Я согласен. Как десериализатор может знать, что вы переименовали? Лучше всего сделать это самостоятельно. - person Alex; 23.10.2014
comment
Я думаю, что я возьму ваш первый вариант. В нашем случае мы проиндексировали данные, сериализованные на жесткий диск, чтобы сохранить обращения к серверу. Так что мы будем делать эту проверку при запуске приложения, которая подходит для одного файла. Спасибо =) - person DerApe; 23.10.2014