Net framework 5, а также среды Visual Studio 2012 и C#



Download 6,27 Mb.
Pdf ko'rish
bet510/658
Sana12.06.2023
Hajmi6,27 Mb.
#950840
1   ...   506   507   508   509   510   511   512   513   ...   658
Bog'liq
CLR via C Programmirovanie na platforme Microsoft NET Framework 4 5 na yazyke C

суррогаты сериализации
До этого момента мы обсуждали способы изменения реализации типов, позволяю-
щие управлять сериализацией и десериализацией их экземпляров. Однако суще-
ствует возможность переопределить поведение этих процессов при помощи кода, 
не принадлежащего реализации типа. Для чего это может быть нужно?
‰
Разработчик может сериализовать типы, для которых возможность сериализации 
не была учтена при исходном проектировании.
‰
Возможность отображения между разными версиями одного типа.
Чтобы этот механизм заработал, нужно определить «суррогатный тип», который 
возьмет на себя работу по сериализации и десериализации существующего типа. 
Затем следует зарегистрировать экземпляр суррогатного типа, сообщив модулю 
форматирования, за действия какого существующего типа он будет отвечать. В ре-
зультате при попытке сериализовать или десериализовать экземпляр существующего 
типа модуль форматирования будет вызывать методы, определенные суррогатным 
объектом. Следующий пример показывает, как все это работает.
Тип суррогата сериализации должен реализовывать интерфейс 
System.Runtime.
Serialization.ISerializationSurrogate
, определяемый в FCL следующим об-
разом:
public interface ISerializationSurrogate {
void GetObjectData(Object obj, SerializationInfo info, 
StreamingContext context);
Object SetObjectData(Object obj, SerializationInfo info, 
StreamingContext context, ISurrogateSelector selector);
}


692
Глава.24 .Сериализация
Теперь посмотрим на пример использования этого интерфейса. Предположим, 
программа содержит объекты 
DateTime
, значения которых привязаны к компьютеру 
пользователя. Каким образом сериализовать эти объекты в поток ввода-вывода, 
указав их значения, как всемирное время? Ведь только при таком подходе вы мо-
жете перенаправить поток на машину, расположенную на другом конце планеты, 
сохранив корректные значения даты и времени. Так как вы не можете менять тип 
DateTime
, представленный в FCL, остается определить собственный суррогатный 
класс, управляющий сериализацией и десериализацией объектов 
DateTime
. Вот 
как он выглядит:
internal sealed class UniversalToLocalTimeSerializationSurrogate :
ISerializationSurrogate {
public void GetObjectData(
Object obj, SerializationInfo info, StreamingContext context) {
// Переход от локального к мировому времени
info.AddValue("Date", ((DateTime)obj).ToUniversalTime().ToString("u"));
}
public Object SetObjectData(Object obj, SerializationInfo info, 
StreamingContext context, ISurrogateSelector selector) {
// Переход от мирового времени к локальному
return DateTime.ParseExact(
info.GetString("Date"), "u", null).ToLocalTime();
}
}
Здесь метод 
GetObjectData
работает почти как одноименный метод интерфейса 
ISerializable
. Отличается он всего одним параметром: ссылкой на «реальный» объ-
ект, который требуется сериализовать. В показанном варианте метода 
GetObjectData
данный объект приводится к типу 
DateTime
, его значение преобразуется из локаль-
ного в универсальное время, а полученная в итоге строка (отформатированная 
с использованием универсального шаблона полной даты/времени) добавляется 
в коллекцию 
SerializationInfo
.
Для десериализации объекта 
DateTime
вызывается метод 
SetObjectData
. Ему 
передается ссылка на объект 
SerializationInfo
. Метод извлекает из коллекции 
строковые данные, разбирает их как строку в формате универсальной полной 
даты/времени и преобразует полученный объект 
DateTime
в формат локального 
машинного времени.
Первый параметр метода 
SetObjectData
, объект 
Object
, выглядит немного стран-
но. Непосредственно перед вызовом метода модуль форматирования выделяет место 
(через статический метод 
GetUninitializedObject
класса 
FormatterServices
) под 
экземпляр типа, для которого предназначается суррогат. Все поля этого экземпляра 
имеют значение 0 или 
null
, и для объекта не вызывается никаких конструкторов. 
Метод 
SetObjectData
может просто инициализировать его поля, используя значения 
из переданного методу объекта 
SerializationInfo
, а затем вернуть значение 
null

В качестве альтернативы метод 
SetObjectData
может создать совсем другой объект 


693
Суррогаты.сериализации
или даже другой объектный тип и вернуть ссылку на него. В этом случае модуль 
форматирования проигнорирует любые изменения, которые могли произойти 
с объектом, переданным им в метод 
SetObjectData
.
В моем примере класс 
UniversalToLocalTimeSerializationSurrogate
действует 
как суррогат для значимого типа 
DateTime
. И поэтому параметр 
obj
ссылается на 
упакованный экземпляр типа 
DateTime
. Менять поля в большинстве значимых 
типов нельзя (так как они предполагаются неизменными), поэтому мой метод 
SetObjectData
игнорирует параметр 
obj
и возвращает новый объект 
DateTime
с нужным значением.
Как же при сериализации/десериализации объекта 
DateTime
модуль форматиро-
вания узнает о необходимости использования типа 
ISerializationSurrogate
? Сле-
дующий код тестирует класс 
UniversalToLocalTimeSerializationSurrogate
:
private static void SerializationSurrogateDemo() {
using (var stream = new MemoryStream()) {
// 1. Создание желаемого модуля форматирования
IFormatter formatter = new SoapFormatter();
// 2. Создание объекта SurrogateSelector
SurrogateSelector ss = new SurrogateSelector();
// 3. Селектор выбирает наш суррогат для объекта DateTime
ss.AddSurrogate(typeof(DateTime), formatter.Context,
new UniversalToLocalTimeSerializationSurrogate());
// ПРИМЕЧАНИЕ. AddSurrogate можно вызывать более одного раза
// для регистрации нескольких суррогатов
// 4. Модуль форматирования использует наш селектор
formatter.SurrogateSelector = ss;
// Создание объекта DateTime с локальным временем машины
// и его сериализация
DateTime localTimeBeforeSerialize = DateTime.Now;
formatter.Serialize(stream, localTimeBeforeSerialize);
// Поток выводит универсальное время в виде строки,
// проверяя, что все работает
stream.Position = 0;
Console.WriteLine(new StreamReader(stream).ReadToEnd());
// Десериализация универсального времени и преобразование
// объекта DateTime в локальное время
stream.Position = 0;
DateTime localTimeAfterDeserialize = 
(DateTime)formatter.Deserialize(stream);
// Проверка корректности работы
Console.WriteLine(
"LocalTimeBeforeSerialize ={0}", localTimeBeforeSerialize);
продолжение



694
Download 6,27 Mb.

Do'stlaringiz bilan baham:
1   ...   506   507   508   509   510   511   512   513   ...   658




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish