ISerializable и обратная совместимость

Я должен работать старое приложение, которое использовало binaryFormatter для сериализации данных приложения в filestream (скажите в файле, названном "data.oldformat") без любого optimizazion основной класс был отмечен с атрибутом

<serializable()>public MainClass
....... 
end class

и код сериализации

dim b as new binaryformatter
b.serialize(mystream,mymainclass)

В попытке оптимизировать сериализацию/десериализацию обрабатывают, я просто заставил класс реализовать интерфейс ISerializable и записал некоторые оптимизированные стандартные программы сериализации

<serializable()>public MainClass
       implements ISerializable
....... 
end class

Оптимизация работает действительно хорошо, но я ДОЛЖЕН найти путь к reatrive данными в старых файлах для обратной совместимости.

Как я могу сделать это??

Pierluigi

6
задан pierusch 10 April 2010 в 15:34
поделиться

4 ответа

Просто попробуйте то же самое, что вы делали до сих пор.

BinaryFormatter b = new BinaryFormatter();
MainClass a = b.DeSerialize(mystream) as MainClass;

Реализация ISerializable не изменила ваш исходный класс, в основном вы только что добавили методы

0
ответ дан 16 December 2019 в 21:37
поделиться

поскольку вы уже реализовали интерфейс ISerializable, вы, вероятно, также уже добавили необходимый конструктор:

public MainClass(SerializationInfo info, StreamingContext context) {}

вы можете использовать info-объект, переданный конструктору, для получения данных из сериализованного файла. по умолчанию (т.е. когда не реализован ISerializable), имена полей используются в качестве идентификаторов при сериализации. так что если ваш старый класс имел поле "int x", вы можете десериализовать его, используя:

this.x = info.GetInt32("x");

для более новых версий я обычно добавляю запись "version" при сериализации, как это:

public void GetObjectData(SerializationInfo info, StreamingContext context) {
  info.AddValue("version", 1);
  info.AddValue("othervalues", ...);
}

при десериализации вы можете проверить эту запись версии и десериализовать соответственно:

public MainClass(SerializationInfo info, StreamingContext context) {
    int version;
    try {
       version = info.GetInt32("version");
    }
    catch {
       version = 0;
    }

    switch (version) {
      case 0:
        // deserialize "old format"
        break;
      case 1:
        // deserialize "new format, version 1"
        break;
      default:
        throw new NotSupportedException("version " + version + " is not supported.");
    }
}

я не компилировал этот код, может содержать опечатки.

надеюсь, это поможет.

4
ответ дан 16 December 2019 в 21:37
поделиться

При сериализации ваших объектов добавьте дополнительное поле Version (это не должно добавить слишком много накладных расходов). Затем в методе GetObjectData попытайтесь сначала получить поле версии и на основании того, существует оно или нет (поймав SerializationException), выполните десериализацию старым или новым способом. При старом способе все данные будут просто сериализованы, поэтому вы сможете просто вызвать Get... для всех полей.

0
ответ дан 16 December 2019 в 21:37
поделиться

Ваш предыдущий код должен работать. Вы получаете исключение? Попробуйте использовать новый конструктор:

 Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
0
ответ дан 16 December 2019 в 21:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: