Переопределение сборки и/или типа
при десериализации объекта
В процессе сериализации объекта модули форматирования выводят в поток полное
имя типа и полное имя определяющей этот тип сборки. При десериализации эта
696
Глава.24 .Сериализация
информация позволяет им точно узнать тип конструируемого и инициализируе-
мого объекта. При обсуждении интерфейса
ISerializationSurrogate
я продемон-
стрировал механизм, позволяющий производить сериализацию и десериализацию
определенного типа. Тип, реализующий интерфейс
ISerializationSurrogate
,
привязан к определенному типу в определенной сборке.
Однако бывают ситуации, когда указанный механизм оказывается недостаточно
гибким. Вот ситуации, в которых может оказаться полезным десериализация объ-
екта в другой тип:
Перемещение реализации типа из одной сборки в другую. Например, номер
версии сборки меняется, и новая сборка начинает отличаться от исходной.
Объект с сервера сериализуется в поток, отправляемый на сторону клиента. При
обработке потока клиент может десериализовать объект в совершенно другой
тип, код которого «знает», как удаленным методом обратиться к объектам на
сервере.
Разработчик создает новую версию типа и именно в нее требуется десериали-
зовать все ранее сериализованные объекты.
Десериализация объектов в другой тип легко выполняется при помощи класса
System.Runtime.Serialization.SerializationBinder
. Достаточно определить
тип, производный от абстрактного типа
SerializationBinder
. В показанном далее
коде предполагается, что версия 1.0.0.0 сборки определяет класс с именем
Ver1
.
И эта новая версия определяет класс
Ver1ToVer2SerializationBinder
и класс
с именем
Ver2
:
internal sealed class Ver1ToVer2SerializationBinder : SerializationBinder {
public override Type BindToType(String assemblyName, String typeName) {
// Десериализация объекта Ver1 из версии 1.0.0.0 в объект Ver2
// Вычисление имени сборки, определяющей тип Ver1
AssemblyName assemVer1 = Assembly.GetExecutingAssembly().GetName();
assemVer1.Version = new Version(1, 0, 0, 0);
// При десериализации объекта Ver1 версии v1.0.0.0 превращаем его в Ver2
if (assemblyName == assemVer1.ToString() && typeName == "Ver1")
return typeof(Ver2);
// В противном случае возвращаем запрошенный тип
return Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
}
}
После создания модуля форматирования нужно создать экземпляр
Ver1-
ToVer2SerializationBinder
и присвоить открытому для чтения и записи свойству
Binder
ссылку на объект привязки. После этого можно вызывать метод
Deserialize
.
В процессе десериализации модуль форматирования обнаружит привязку и для
каждого обрабатываемого объекта вызовет метод
BindToType
, передавая ему имя
697
Переопределение.сборки.и/или.типа.при.десериализации.объекта
сборки и тип, которые требуется десериализовать. На этой стадии метод
BindToType
решает, какой тип следует сконструировать, и возвращает этот тип.
Do'stlaringiz bilan baham: |