Глава.24 .Сериализация
После создания модуля форматирования можно создать структуру
Streaming-
Context
, используя любые битовые флаги
StreamingContextStates
, с возмож-
ностью передачи ссылки на объект, содержащий дополнительную контекстную
информацию. После чего остается присвоить свойству
Context
новый объект
StreamingContext
до вызова метода
Serialize
или
Deserialize
. Показанный
ранее метод
DeepClone
демонстрирует, как сообщить модулю форматирования,
что сериализация/десериализация графа объектов выполняется исключительно
с целью клонирования всех объектов.
сериализация в другой тип
и десериализация в другой объект
Инфраструктура сериализации в .NET Framework обладает достаточно широкими
возможностями. В частности, она позволяет разработчикам создавать типы, до-
пускающие сериализацию и десериализацию в другой тип или объект. Несколько
примеров ситуаций, в которых это может быть нужно:
Некоторые типы (например,
System.DBNull
и
System.Reflection.Missing
)
допускают существование в домене приложений только одного экземпляра.
Их часто называют
одноэлементными
(singleton). Если у вас имеется ссылка
на
DBNull
, ее сериализация и десериализация не приведет к созданию в домене
нового объекта. Возвращаемая после десериализации ссылка должна указывать
на уже существующий в домене объект
DBNull
.
Некоторые типы (например,
System.Type
,
System.Reflection.Assembly
и другие
связанные с отражениями типы, такие как
MemberInfo
) допускают существование
всего одного экземпляра на тип, сборку, член и т. п. Представьте массив ссылок
на объекты
MemberInfo
. Допустима ситуация, когда пять ссылок указывают на
один объект. Это состояние должно сохраняться и после сериализации и десе-
риализации. Более того, элементы должны ссылаться на объект
MemberInfo
,
существующий в домене для определенного члена. Такой подход полезен также
для последовательного опроса объектов подключения к базе данных и любых
других типов объектов.
Для объектов, контролируемых удаленно, CLR сериализует информацию о сер-
верном объекте таким образом, что при десериализации на клиенте CLR создает
объект, являющийся
представителем
(proxy) сервера на стороне клиента. Тип
представителя отличается от типа серверного объекта, но для клиентского кода
эта ситуация прозрачна. Если клиент вызывает для объекта-представителя эк-
земплярные методы, код представителя переправляет вызов на сервер, который
в действительности и обрабатывает запрос.
Следующий пример демонстрирует корректное выполнение сериализации
и десериализации одноэлементного типа:
689
Сериализация.в.другой.тип.и.десериализация.в.другой.объект
// Разрешен только один экземпляр типа на домен
[Serializable]
public sealed class Singleton : ISerializable {
// Единственный экземпляр этого типа
private static readonly Singleton theOneObject = new Singleton();
// Поля экземпляра
public String Name = "Jeff";
public DateTime Date = DateTime.Now;
// Закрытый конструктор для создания однокомпонентного типа
private Singleton() { }
// Метод, возвращающий ссылку на одноэлементный тип
public static Singleton GetSingleton() { return theOneObject; }
// Метод, вызываемый при сериализации объекта Singleton
// Рекомендую использовать явную реализацию интерфейсного метода.
[SecurityPermissionAttribute(
SecurityAction.Demand, SerializationFormatter = true)]
void ISerializable.GetObjectData(
SerializationInfo info, StreamingContext context) {
info.SetType(typeof(SingletonSerializationHelper));
// Добавлять другие значения не нужно
}
[Serializable]
private sealed class SingletonSerializationHelper : IObjectReference {
// Метод, вызываемый после десериализации этого объекта (без полей)
public Object GetRealObject(StreamingContext context) {
return Singleton.GetSingleton();
}
}
// ПРИМЕЧАНИЕ. Специальный конструктор НЕ НУЖЕН,
// потому что он нигде не вызывается
}
Класс
Singleton
представляет тип, для которого в домене приложений может
существовать только один экземпляр. Показанный далее код тестирует процеду-
ры сериализации и десериализации этого типа, обеспечивая выполнение данного
условия:
private static void SingletonSerializationTest() {
// Создание массива с несколькими ссылками на один объект Singleton
Singleton[] a1 = { Singleton.GetSingleton(), Singleton.GetSingleton() };
Console.WriteLine("Do both elements refer to the same object? "
+ (a1[0] == a1[1])); // "True"
using (var stream = new MemoryStream()) {
BinaryFormatter formatter = new BinaryFormatter();
// Сериализация и десериализация элементов массива
продолжение
690
Do'stlaringiz bilan baham: |