Бинарная сериализация, добавление нового поля в класс - это будет работать?

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

Вопрос

У меня есть клиент и серверное приложение, которое общается Over .net 2.0, удаленная с использованием бинарной сериализации.

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

Если я переведите новую версию серверного приложения, будут ли мои старые клиенты продолжать работать?

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

Вероятно, это сводится к другому вопросу - является бинарным пустынизатором, «достаточно умным», чтобы справиться с такой ситуацией, инициализируя поля, он не может найти данные во входном двоичном потоке, чтобы он был нуль, или будет сломаться и бросить исключение ?

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

Решение

Вы можете добавить атрибут в новое свойство: OptionalField. Анкет Без атрибута Deserializer не сможет преобразовать сериализованные данные обратно в обновленное определение. Атрибут состоит в том, чтобы убедиться, что десериализатор может обработать «отсутствующие» данные изящно.

Если вы хотите установить значение по умолчанию для нового свойства, в том случае, если нет соответствующих данных для его детериализации, реализуйте IDeserializationCallback интерфейс и установите значение по умолчанию, если таковые имеются, в полученном методе.

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

Скорее всего, это сделает исключение, вы всегда можете реализовать свой собственный сериализатор, унаследовав от ISerializable и реализовать управление версиями, используя свои собственные методы GetObjectData... это даст вам более жесткую степень контроля над данными, которые будут сериализованы ... Вот пример

using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class MyFooBar : ISerializable{
    private float _fVersion = 1.0;
    public MyFooBar(SerializationInfo info, StreamingContext context) {
         this._fVersion = info.GetSingle("FooBarVersionID");
         if (this._fVersion == 1.0F) bOk = this.HandleVersionOnePtZero(info, context);
         if (!bOk) throw new SerializationException(string.Format("MyFooBar: Could not handle this version {0}.", this._fVersion.ToString()));
    }
    [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand, Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)]
   public void GetObjectData(SerializationInfo info, StreamingContext context) {
       info.AddValue("FooBarVersionID", this._fVersion);
       if (this._fVersion == 1.0F) {
          // Bool's...
          info.AddValue("FooBarBool", FooBarBool);
          // etc... for Version 1.0
       }
       if (this._fVersion == 1.1F){
          // etc... for Version 1.0
       }
   }
}

И используйте Myfoobar в этом контексте при сериализации/десериализации, как показано ниже

public bool Deserialize(string sFileName) {
            bool bSuccessful = false;
            //
            if (!System.IO.File.Exists(sFileName)) return false;
            fuBar = new MyFooBar();
            //
            try {
                using (FileStream fStream = new FileStream(sFileName, FileMode.Open)) {
                    try {
                        BinaryFormatter bf = new BinaryFormatter();
                        fuBar = (MyFooBar)bf.Deserialize(fStream);
                        bSuccessful = true;
                    } catch (System.Runtime.Serialization.SerializationException sEx) {
System.Diagnostics.Debug.WriteLine(string.Format("SERIALIZATION EXCEPTION> DETAILS ARE {0}", sEx.ToString()));
                        bSuccessful = false;
                    }
                }
            } catch (System.IO.IOException ioEx) {
                System.Diagnostics.Debug.WriteLine(string.Format("IO EXCEPTION> DETAILS ARE {0}", ioEx.ToString()));
                bSuccessful = false;
            }
            return (bSuccessful == true);
        }

Есть более аккуратный способ сделать это в 2.0+ вверх, но я предпочитаю это.

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