В MSDN описано понятие Version Tolerant Serialization (VTS), которое обозначает сериализацию, «терипимую» к изменению версии.
Version Tolerant Serialization — это набор фич, включенных в .NET Framework 2.0, которые облегчают внесение изменений в сериализуемые классы. VTS доступно для классов, помеченных атрибутом
SerializableAttribute
. Благодаря VTS можно добавлять новые поля к классам без нарушения совместимости с сериализованными данными предыдущих версий. Фичи VTS работают когда используетсяBinaryFormatter
и частично работают дляSoapFormatter
.
В частности VTS позволяет добавить свойства в класс и при этом:
- старые версии приложения смогут работать с новой версией сериализованного класса, игнорируя неизвестное поле (Tolerance of Extraneous or Unexpected Data).
- новые версии приложения смогут десериализовать старые классы, задавая пропущенным свойствам значения по умолчанию (Tolerance of Missing Data).
Пункт 1 работает из коробки, а вот для пункта 2 нужно пометить соответствующее поле атрибутом OptionalFieldAttribute
:
[Serializable]
public class Customer
{
public string FirstName;
public string LastName;
[OptionalField]
public string Country;
}
Атрибут OptionalFieldAttribute
имеет свойство VersionAdded
, которое хранит порядковый номер версии файла (начиная с 2). Каждый раз при добавлении нового свойства в класс нужно помечать это поле атрибутом OptionalFieldAttribute
и указывать версию изменения.
Если при десериализации не удается найти значение какого-то из свойств/полей, то этому свойству/полю присваивается значение по умолчанию. Чтобы изменить такое поведение нужно использовать специальные атрибуты, позволяющие реагировать на события (де)сериализации:
- OnDeserializingAttribute — отмечается метод, который будет вызван перед десериализацией;
- OnDeserializedAttribute — отмечается метод, который будет вызван после десериализацией;
- OnSerializingAttribute — отмечается метод, который будет вызван перед сериализацией;
- OnSerializedAttribute — отмечается метод, который будет вызван после сериализацией;
Пример использования:
[Serializable]
public class Customer
{
public string FirstName;
public string LastName;
[OptionalField]
public string Country;
[OnDeserializing]
private void ResetCountry (StreamingContext sc)
{
Country = "Россия";
}
}
У описанного подхода есть серьезные недостатки: во-первых, он работает только с бинарной сериализацией (поправьте если тут я ошибаюсь), и во-вторых, если сериализуется сложный граф объектов, структура которого меняется от версии к версии, то средств VTS становится явно недостаточно.