Игнорировать устаревшее поле при десериализации

Я весь день искал способ добиться этого безрезультатно...

Я пытаюсь десериализовать объект. Когда я его сериализовал, у меня было логическое значение, называемое, скажем, obsoleteBool. В новой версии класса я убрал этот bool, и теперь у меня возникает ошибка при десериализации (Поле «obsoleteBool» не найдено).

Добавлять новые поля между старой и новой версией класса очень просто. Даже без использования атрибута [OptionalField]... но как мне управлять удалением поля между старой и новой версией класса?


person Ryan Pergent    schedule 03.08.2014    source источник
comment
Я отредактировал ваш заголовок. См. Должны ли вопросы включать «теги» в свои заголовки?, если нет единого мнения, не следует.   -  person John Saunders    schedule 03.08.2014
comment
Реализация ISerializable. Это потребует времени и усилий, но у вас будет гораздо больше контроля (и вы сможете, грубо говоря, управлять версиями).   -  person Adriano Repetti    schedule 03.08.2014
comment
Чем вы его сериализуете?   -  person ahruss    schedule 03.08.2014
comment
Я хочу, чтобы мой класс был расширен пользователями. Насколько я понял, использование ISerializable потребует от них управления сериализацией новых переменных, которые они будут создавать. Когда я использую атрибут [Serializable], они могут создать новую переменную, ничего не делая для ее сохранения. @ahruss: я сериализую с помощью BinaryFormatter   -  person Ryan Pergent    schedule 03.08.2014


Ответы (1)


Есть 3 возможных решения:

  • Самый простой: добавьте старое поле в новую версию класса.
  • Пользовательский код: реализация пользовательского десериализатора
  • Дополнительная работа: напишите программу преобразования, которая проходит через все сериализованные классы, считывает их в старом формате и повторно сериализует в соответствии с определением нового класса.

С точки зрения ценности бизнеса первый вариант, вероятно, предпочтительнее.

person Shiraz Bhaiji    schedule 03.08.2014
comment
Поскольку пользователи будут расширять мой класс и, вероятно, будут много итерировать между сериализацией, мне нужно самое чистое возможное решение. Сохранение устаревшего поля может быстро привести к чрезвычайно грязному коду, не говоря уже о людях, которые могут решить не переименовывать переменную из-за этого и в конечном итоге получить несоответствующее имя или подобные проблемы. Сможет ли пользовательский сериализатор автоматически учитывать новые поля, созданные пользователями? Что касается программы преобразования, как я вообще смогу открыть классы для преобразования, если при попытке у меня появляется сообщение об ошибке с отсутствующим полем? - person Ryan Pergent; 04.08.2014
comment
@RyanPergent с ISerializable вы также можете управлять полями в производных классах (как это делает BinaryFormatter). Конечно, это не лучшее решение, но вы можете это сделать (через Reflection). Чтобы выполнить преобразование, вам необходимо развернуть обе версии (с дополнительным полем и без него), десериализовать в одном AppDomain, переместить десериализованные данные в новый формат во втором AppDomain. Довольно трудно. Весь смысл IMO в том, что сериализация НЕ является инструментом для использования с файлом данных (с управлением версиями). Это полезно для многих вещей, но не для этого (потому что после нескольких версий это сделает ваш код беспорядочным, и если вы когда-нибудь измените иерархию...) - person Adriano Repetti; 04.08.2014
comment
Я пытаюсь реализовать метод ISerializable прямо сейчас. Неудобство только в том, что мне нужно иметь конструктор с SerializationInfo и StreamingContext во всех классах, наследующихся от дефолтного (у меня их предостаточно). Но это незначительный дефект по сравнению с невозможностью удаления переменных. Однако я столкнулся с другой проблемой: я использую Reflection для получения и сохранения всех полей, но мне нужно получить только те [Serializable]. BindingFlags, похоже, не предлагает такой фильтрации... Кто-нибудь знает, как я могу фильтровать свои поля таким образом? - person Ryan Pergent; 04.08.2014
comment
Мне удалось отфильтровать их с помощью IsNotSerialized из System.Reflection.FieldInfo :) Большое спасибо за вашу помощь, ребята, я думаю, что теперь мне удастся добиться того, чего я хочу. - person Ryan Pergent; 04.08.2014