Переименование полей, а затем десериализация в C # - PullRequest
6 голосов
/ 03 июня 2009

У меня есть данные, хранящиеся в экземпляре класса, который был сериализован с помощью .net BinaryFormatter. Теперь я хочу переименовать одно из полей в классе, но все же иметь возможность десериализовать старые данные.

Один из вариантов - реализовать ISerializable и десериализовать все поля класса вручную. Но это похоже на большую работу, особенно если в моем классе много полей, и я переименовал только одно поле.

Есть ли лучший способ?


Крейг предлагает сохранить копию старого класса для десериализации и скопировать значения в новый класс. Я видел это и в другом месте - какое это имеет преимущество перед реализацией ISerializable? Насколько я вижу, при копировании класса у меня остается 2 практически идентичных копии класса, и мне все еще приходится копировать все значения из старого класса в новый класс, что, по-видимому, требует столько же усилий, сколько и реализация ISerializable с почти дублированный класс, брошенный в смесь.


В двух ответах упоминается Binder. Я успешно использовал SerializationBinder для десериализации класса Bar, который был Serialized как класс Foo, но это потому, что имя класса изменилось. Помогает ли SerializationBinder при переименовании поля - например, когда int m_Left был переименован в int m_Right?

Ответы [ 4 ]

2 голосов
/ 03 июня 2009

Да, это проблема полевых сериализаторов. Вы можете использовать либо пользовательский Binder, либо «заменитель сериализации», чтобы избежать реализации ISerializable, но это только индивидуальное исправление.

Я обсуждал эту тему (в контексте обфускаторов и авто-реквизитов) здесь . Мой совет: не используйте BinaryFormatter для сохранения данных между версиями ... для этого посмотрите на контрактные сериализаторы:

  • XmlSerializer
  • DataContractSerializer
  • или для двоичных файлов, например protobuf-net

Ничего из этого не поможет сегодня , но это может помочь вам спроектировать его в будущем.

2 голосов
/ 03 июня 2009

Вы можете попытаться заставить старого кальса зависать с единственной целью регидратации, а затем просто скопировать необходимые поля в новый класс. Все еще немного болезненно, но должно работать.

0 голосов
/ 03 июня 2009

Что делать, если вы просто измените модификатор доступа в этом одном свойстве на private, а затем у вас будет открытое свойство с новым именем, которое в основном обернет старое. Таким образом, вы все равно сможете десериализовать (я думаю), но любой, кто использует этот класс, не будет знать о старом имени. Просто мысль ...

0 голосов
/ 03 июня 2009

Я использовал класс SerializationBinder для этого до

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.serializationbinder.aspx

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...