Как реорганизовать класс, сериализованный в .NET?

У меня есть класс C#, который сериализуется на диск с помощью BinaryFormatter, как в этом примере:

// Version 3.0
[Serializable]
public class Person
{
    public string FullName;

    [OptionalField(VersionAdded=2)]
    public string NickName;
    [OptionalField(VersionAdded=2)]
    public DateTime BirthDate;

    [OptionalField(VersionAdded=3)]
    public int Weight;
}

Позже я хочу реорганизовать этот класс одним или несколькими из следующих способов
- изменить его имя
- изменить его пространство имен
- переместить в другую сборку

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

Как обойти это?
Можно ли сопоставить десериализацию с другим именем класса, пространством имен и сборкой без нарушения Сериализация с поддержкой версий?


person angularsen    schedule 23.08.2010    source источник


Ответы (2)


После некоторых исследований я понял, что BinaryFormatter действительно поддерживает все, что я искал.

BinaryFormatter может использовать суррогаты для

  1. Предоставляет возможность сериализовать тип, который изначально не был предназначен для сериализации.
  2. Предоставляет способ сопоставления одной версии типа с другой версией другого типа.

Можно также преобразовать десериализацию из типа A в тип B (другое имя класса, пространство имен и/или имя сборки) с помощью SerializationBinder.

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

Ссылка: http://www.diranieh.com/NETSerialization/BinarySerialization.htm

Изменить. Кстати, рефакторинг полей (имя или тип) по-прежнему является проблемой, как обсуждалось в Переименование полей с последующей десериализацией в C#. В настоящее время я изучаю protobuf-net, чтобы лучше решить эту проблему в будущем.

person angularsen    schedule 28.09.2010

Вы можете реализовать интерфейс ISerializable и переопределить GetObjectData для обеспечения собственной десериализации . Я не пробовал, но вы должны иметь возможность десериализовать свой старый объект «вручную».

person Albin Sunnanbo    schedule 23.08.2010
comment
То есть вы имеете в виду, что Person должен реализовать ISerializable и GetObjectData()? Как десериализатор узнает, что следует использовать именно этот класс Person, если у него другое имя, пространство имен и/или сборка? Могу ли я как-то указать десериализатору, какой класс использовать? - person angularsen; 23.08.2010