ПриМеЧание
Перед.вами.интересный.и.полезный.метод,.использующий.сериализацию.для.соз-
дания.глубокой.копии.(клона).объекта:
private static Object DeepClone(Object original) {
// Создание временного потока в памяти
using (MemoryStream stream = new MemoryStream()) {
// Создания модуля форматирования для сериализации
BinaryFormatter formatter = new BinaryFormatter();
// Эта строка описывается в разделе "Контексты потока ввода-вывода"
formatter.Context = new StreamingContext(StreamingContextStates.Clone);
// Сериализация графа объекта в поток в памяти
продолжение
670
Глава.24 .Сериализация
formatter.Serialize(stream, original);
// Возвращение к началу потока в памяти перед десериализацей
stream.Position = 0;
// Десериализация графа в новый набор объектов и возвращение
// корня графа (детальной копии) вызывающему методу
return formatter.Deserialize(stream);
}
}
Здесь я хотел бы добавить несколько замечаний. Во-первых, следует следить за
тем, чтобы сериализация и десериализация производилась одним и тем же модулем
форматирования. К примеру, недопустим код, в котором сериализация графа объекта
производится модулем
SoapFormatter
, в то время как десериализацию осуществля-
ет уже
BinaryFormatter
. Если метод
Deserialize
не в состоянии расшифровать
содержимое потока, генерируется исключение
System.Runtime.Serialization.
SerializationException
.
Во-вторых, хотелось бы упомянуть о возможности и полезности сериализации
набора графов объектов в единый поток. Например, пусть у нас есть два опреде-
ления классов:
[Serializable] internal sealed class Customer { /* ... */ }
[Serializable] internal sealed class Order { /* ... */ }
Тогда в основном классе нашего приложения можно определить следующие
статические поля:
private static List s_customers = new List();
private static List s_pendingOrders = new List();
private static List s_processedOrders = new List();
Теперь при помощи показанного далее метода можно сериализовать состояние
нашего приложения в единый поток:
private static void SaveApplicationState(Stream stream) {
// Конструирование модуля форматирования для сериализации
BinaryFormatter formatter = new BinaryFormatter();
// Сериализация всего состояния приложения
formatter.Serialize(stream, s_customers);
formatter.Serialize(stream, s_pendingOrders);
formatter.Serialize(stream, s_processedOrders);
}
Метод, используемый для восстановления состояния приложения, выглядит
примерно так:
private static void RestoreApplicationState(Stream stream) {
// Конструирование модуля форматирования сериализации
671
Практический.пример.сериализации/десериализации
BinaryFormatter formatter = new BinaryFormatter();
// Десериализация состояния приложения (выполняется в том же
// порядке, что и сериализация)
s_customers = (List ) formatter.Deserialize(stream);
s_pendingOrders = (List) formatter.Deserialize(stream);
s_processedOrders = (List) formatter.Deserialize(stream);
}
Третий тонкий момент, на который хотелось бы указать, связан со сборками. При
сериализации объекта в поток записываются полное имя типа и определяющая его
сборка. По умолчанию
BinaryFormatter
выдает полный идентификатор сборки,
в который входит ее полное имя (без расширения), номер версии, язык, региональ-
ные параметры и открытый ключ. Десериализуя объект, модуль форматирования
берет идентификатор сборки и обеспечивает ее загрузку в выполняющийся домен
при помощи метода
Load
класса
System.Reflection.Assembly
(о нем шла речь
в главе 23).
После загрузки сборки модуль форматирования ищет в нем тип, совпадающий
с типом десериализованного объекта. Если сборка не содержит такого типа, генери-
руется исключение, и дальнейшая десериализация объектов не выполняется. При
обнаружении же нужного типа создается его экземпляр, и поля этого экземпляра
инициализируются значениями, содержащимися в потоке. В случаях, когда поля
типа не полностью совпадают с именами полей, считанными из потока, генериру-
ется исключение
SerializationException
и дальнейшая десериализация объектов
приостанавливается. Механизмы, позволяющие переопределить такое поведение,
мы обсудим чуть позже.
Do'stlaringiz bilan baham: |