Десериализация измененного класса - PullRequest
1 голос
/ 10 ноября 2011

Я работаю над программой, где я сохраняю файлы проекта, сериализуя класс Project.Поскольку я все еще работаю над этим, некоторые классы, являющиеся частью класса Project, время от времени меняются (например, класс получает новое свойство).Это делает «простую» десериализацию невозможной.

Есть ли способ ее решить?Я имею в виду, без написания собственного сериализатора?(что, вероятно, сейчас намного выше моего уровня)

На всякий случай, я использую BinaryFormatter.


Как я писал ниже, я нашел решение, котороеЯ буду работать на меня. Но я не могу проверить свой ответ как правильный ответ;) Спасибо за каждый ответ и комментарий, которые помогли мне найти другие способы решения проблем десериализации, которые я могу использовать в других своих проектах.

Ответы [ 3 ]

3 голосов
/ 10 ноября 2011

Надеюсь, я правильно понял вашу проблему. У вас есть класс, сериализованный в файл. Затем вы изменяете класс в памяти (например, добавляете другое свойство). Нет, вы хотите десериализовать этот класс из файла. Это не проблема, пока вы только добавляете новых свойств. Они будут проигнорированы десериализатором. Он создает новый экземпляр вашего класса (по этой причине сериализуемые классы должны иметь конструктор по умолчанию ) и пытается заполнить свойства, которые он находит в потоке, для десериализации. Если вы измените тип свойства или удалите свойство, вы не сможете десериализовать его.

Один обходной путь для «удаления свойств» может быть для сохранения свойств, которые вы намеренно хотели удалить, и игнорировать их. Обходной путь для свойств, которые изменили свой тип, может быть такой, например:

[Serializable]
public class MyClass
{
     int? newProperty;
     [XmlElement("Property")]
     public string OldProperty 
     {
         get { return string.Empty; }
         set 
         { 
             if (!newProperty.HasValue)
             {
                  int temp;
                  if (int.TryParse(value, out temp))
                  {
                       newProperty.Value = temp;
                  }
             }
         }
     }

     public int NewProperty
     {
         get { return newPropery.HasValue ? newProperty.Value : 0; }
         set { newProperty.Value = value;
     }
} 
1 голос
/ 10 ноября 2011

С помощью комментариев Мерлина Моргана-Грэма я нашел решение, которое будет работать для меня.

Версия, описанная в Версия Tolerant Serialization действительно хорошаидея, но когда я использую только атрибут [Serializable].

Я забыл написать (моя ошибка), что я использую интерфейс ISerializable.Я обнаружил, что в конструкторе десериализации объект SerializationInfo имеет свойство MemberCount, которое решает мою проблему, если я только время от времени добавляю новые свойства / члены.С этой информацией, новые члены / свойства, которые не могут быть десериализованы из более старого файла, могут быть установлены по умолчанию или, возможно, я могу использовать некоторую форму приглашения.

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

В любом случае, я согласен с Мерилин - «если вы не можете что-то написать, вы не должны создавать это».;)

1 голос
/ 10 ноября 2011

Из моего опыта я обнаружил, что использование BinaryFormatter для сериализации / десериализации типов данных, которые могут изменить действительно плохую идею. Если что-то изменится в вашем типе данных, из того, что я знаю, BinaryFormatter потерпит неудачу в процессе.

Чтобы преодолеть эту проблему в типах данных, которые я использовал, мне пришлось написать собственный сериализатор, который на самом деле не был такой большой задачей. Вы можете использовать классы BinaryReader и BinaryWriter для чтения и записи данных в и из вашего типа. Таким образом, вы можете контролировать ожидаемые данные и обрабатывать любые отсутствующие данные, либо добавляя значения по умолчанию, либо пропуская свойство полностью, либо выбрасывая некоторую форму Exception для обозначения поврежденных данных. Для получения дополнительной информации см. Ссылки на статьи MSDN выше.

...