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

StackOverflow https://stackoverflow.com/questions/1260771

Вопрос

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

[Serializable]
public abstract class BaseBusinessObject
{
    private NameValueCollection _fieldErrors = new NameValueCollection();

    protected virtual NameValueCollection FieldErrors
    {
        get { return _fieldErrors; }
        set { _fieldErrors = value; }
    }

    ...
}

В какой-то момент класс был изменен на этот:

[Serializable]
public abstract class BaseBusinessObject
{
    private Dictionary<string, string> _fieldErrors = new Dictionary<string, string>();

    protected virtual Dictionary<string, string> FieldErrors
    {
        get { return _fieldErrors; }
        set { _fieldErrors = value; }
    }

    ...
}

Это вызывает проблемы с десериализацией старых данных.

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

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

Это было полезно?

Решение

Добавьте новый _fieldErrors под другим именем, скажем _fieldErrors2, и сделай это [Optional].Затем реализуйте [OnDeserialized] Метод, копирующий данные из _fieldErrors к _fieldErrors2 (если присутствует) и очищает _fieldErrors.

Другие советы

Если данные используются только внутри, моей первой мыслью было бы написать какой-нибудь простой одноразовый код для десериализации ваших двоичных данных с использованием старой «NameValueCollection», сопоставить их со словарем и повторно сериализовать.Даже если обработка всех данных займет несколько дней, кажется, не стоит вносить исправления в новый код для поддержки старых данных.

Даже если он используется не только внутри страны, импортер кажется самым простым способом.

Добавляя к хорошему совету OlivierD, я бы посоветовал вам определить оба класса, но сначала попытаться десериализовать их как текущую версию.В блоке catch десериализуйте его как устаревшую версию, затем обновите ее до текущей и сохраните обратно.Если экземпляров устаревшей версии не существует, вы можете удалить код.

Рассмотрев несколько вариантов, я сделал следующие выводы:

В идеале я мог бы получить доступ к значению из оригинала NameValueCollection и вручную преобразовать его в Dictionary<string, string>.Единственный способ сделать это - реализовать ISerializable, но это вызвало две основные проблемы:сопоставление имен устаревших данных и включение логики сериализации для всех наследующих классов (которых сотни).

По сути, это поставило меня в тупик.К счастью, мне удалось определить, что это поле на самом деле используется только как сводка ошибок проверки формы и вообще не должно сериализоваться, поэтому я исключил его из сериализации.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top