Вопрос

Я должен работать старое приложение, которое использовало BinaryFormatter для сериализации данных приложения в FileStream (скажем, в файле с именем «data.oldformat») без какой-либо оптимизации основной класс был отмечен атрибутом

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

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

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

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

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

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

Как мне это сделать??

Пирлуги

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

Решение

stmax. Имеет отличный ответ, однако я бы реализовал это, что использует SerializationEntry.GetEnumerator() вместо try/catch. Отказ Этот путь более чистые и значительно быстрее.

public MainClass(SerializationInfo info, StreamingContext context) {
    int version = 0;
    foreach (SerializationEntry s in info)
    {
        if (s.Name == "version") 
        {
            version = (int)s.Value;
            break;
        }
    }

    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.");
    }
}

Я бы предпочел версию LINQ, используя .firstortefault (), но serializzeInfo не реализует iEnumerable - в лицо, странно, это даже не реализует старый интерфейс Ienumerable.

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

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

public MainClass(SerializationInfo info, StreamingContext context) {}

Вы можете использовать информационный объект, переданный конструктору для получения данных из сериализованного файла. По умолчанию (т.е. когда не реализуется iserializable), имена полей используются в качестве идентификаторов во время сериализации. Поэтому, если у вашего старого класса был поле «int x», вы можете определить это использование:

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

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

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.");
    }
}

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

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

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

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

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

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

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

 Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top