Волшебство метаданных
Чтобы решить все проблемы,
связанные с разработкой Windows-приложений,
платформа .NET должна обладать базовым
набором служб, которые в любой момент
доступны в любом языке программирования.
Чтобы предоставить такие службы, платформа
.NET должна иметь достаточно сведений о
приложении.
Сериализация (преобразование в
последовательную форму) объекта может
послужить в качестве простого примера.
Перед каждым программистом, рано или поздно,
возникает проблема сохранения данных. Но
зачем каждому программисту вновь
изобретать колесо, решая вопрос о том, как
следует сохранять вложенные объекты и
сложные структуры данных? Зачем каждому
программисту понимать, как эти объекты и
данные хранятся в разных информационных
хранилищах? Платформа .NET позволяет
выполнить сериализацию объекта без
вмешательства программиста. При желании
разработчик может это сделать и
самостоятельно.
Чтобы понять, как происходит
сериализация объектов, мы рассмотрим
относящийся к данной главе пример Serialize (Сериализация).
Не станем акцентировать внимание на
применяемых приемах программирования. Они
будут рассмотрены позже. Сейчас же мы
сосредоточимся на используемых в этом
примере понятиях.
//Serialize.cs
>fusing <mscorlib.dll>
>fusing <System.Runtime.Serialization.Formatters.Soap.dll>
>// <Система. Время выполнения.
>// Преобразование в
последовательную форму. Форматеры. Soap.dll>
>using namespace System;
>// использование пространства имен
Система;
>using namespace System::Collections;
>// использование пространства имен
Система:: Коллекции;
>using namespace System::10;
>// использование пространства имен
Система:: Ввод-вывод;
>using namespace
>System::Runtime:Serialization::Formatters::Soap; //
использование пространства имен
>// Система:: Время выполнения::
Преобразование в последовательную // форму::
Форматеры:: Soap;
>[Serializable]
>// [Преобразование в
последовательную форму]
>_gc class Customer
>// класс сборщика мусора Клиент
>{
>public:
>String *pname; // Строка long id; //
идентификатор
>};
>_gc class Test
>// класс сборщика мусора Испытание
>{
>public:
>static void Main()
>{
>ArrayList *plist = new ArrayList;
>Customer *pcust = new Customer; // новый Клиент
pcust->pname = "Charles Darwin"; // Чарльз Дарвин
pcust->id = 10; // идентификатор plist->Add(pcust); //
Добавить
>pcust = new Customer; // новый Клиент pcust->pname
= "Isaac Newton"; // Исаак Ньютон pcust->id =20; //
идентификатор plist->Add(pcust); // Добавить
>for (int i=0; i < plist->get_Count(); i++)
>{
>Customer *pcust = // Клиент
>dynamic_cast<Customer _gc *> // <Клиент _
сборщик
>//мусора *> (plist->get_Item(i)); Console::WriteLine(
"{0}: {!}",
>pcust->pname, _box(pcust->id)); //
идентификатор } ~
>Console::WriteLine("Saving Customer List"); // ("Сохранение
списка клиентов"); FileStream *ps = new FileStream(
>"cust.txt", FileMode::Create); // Создать
SoapFormatter *pf = new SoapFormatter; pf->Serialize(ps, plist);
>// Преобразование в
последовательную форму; ps->Close ();
>Console::WriteLine("Restoring to New List");
>// "Восстановить в новом списке");
>ps = new FileStream("cust.txt", FileMode::Open); //
Открыть
>pf = new SoapFormatter();
>ArrayList *plist2 =
>dynamic_cast<ArrayList *>
>(pf->Deserialize(ps)); ps->Close();
>for (int i=0; i < plist->get_Count(); i++) {
>Customer *pcust = // Клиент
>dynamic_cast<Customer _gc *> // <Клиент _
сборщик мусора *>
>(plist->get_Item(i)); Console::WriteLine( "{0}:
{!}",
>pcust->pname, _box(pcust->id)); //
идентификатор } } };
>void main(void) {
>Test::Main(); }
Мы определили класс Customer (Клиент)
с двумя полями: pname и id (идентификатор).
Сначала программа создает экземпляр
коллекции, в котором будут храниться
экземпляры класса Customer (Клиент). Мы
добавляем в коллекцию два объекта Customer (Клиент),
а затем распечатываем содержимое коллекции.
Потом коллекция сохраняется на диске. Она
восстанавливается в новый экземпляр
коллекции и выводится на печать.
Распечатанные теперь данные будут
идентичны данным, которые были распечатаны
перед сохранением коллекции [В результате
инсталляции примеров программ, которыми
сопровождается данная книга, должен быть
создан пример, готовый к выполнению. Если он
отсутствует, щелкните два раза на том файле
решения Visual Studio.NET, который имеет расширение
.sin. Когда откроется Visual Studio, нажмите
комбинацию клавиш CtrI-F5 для того чтобы
построить и выполнить пример.]. Если вы
запустите приложение и откроете
получившийся в результате файл cust. txt, вы
увидите, что он содержит данные в необычном
XML-формате, который известен как простой
протокол доступа к объектам (Simple Object Access
Protocol -r- SOAP). Этот протокол специально
разработан для хранения и передачи
объектов.
Мы не писали код для того, чтобы
указать, как сохраняются или
восстанавливаются поля объекта Customer (Клиент).
Но мы определили формат (SOAP) и создали среду,
в которой затем были сохранены данные.
Классы библиотеки .NET Framework сгруппированы
таким образом, что каждый выбор — среды,
формата и способа загрузки (восстановления)
или сохранения объекта — можно сделать
независимо друг от друга. Такого типа
разделение классов существует в библиотеке
.NET Framework повсеместно.
Класс Customer (Клиент) имеет атрибут
Serializable (Преобразуемый в последовательную
форму, упорядочиваемый). Аналогично поле
имени имеет атрибут public (общедоступный).
Когда вы не хотите, чтобы объект можно было
преобразовывать в последовательную форму,
не приписывайте ему соответствующий
атрибут. Если будет предпринята попытка
сохранения объекта, который не имеет
атрибута Serializable (Преобразуемый в
последовательную форму, упорядочиваемый),
возникнет исключительная ситуация и
произойдет отказ в работе программы [Выделите
в программе атрибут Serializable (Преобразуемый в
последовательную форму, упорядочиваемый)
как комментарий и посмотрите, что при этом
произойдет. Для того чтобы ввести
комментарий в программу, вы можете
использовать синтаксис языка С и C++, то есть
применять пары символов /* и */ в качестве
открывающей и закрывающей цепочек
комментария.].
При программировании на
платформе .NET атрибуты можно применять
повсеместно. Использование атрибутов
позволяет описать способ обработки кода и
данных библиотекой классов .NET Framework. При
помощи атрибутов можно также указать
используемую модель безопасности. Атрибуты
можно использовать для того, чтобы
организовать с помощью каркаса
синхронизацию многопоточной обработки.
Благодаря использованию атрибутов
становится очевидной идея удаленного
размещения объектов.
Чтобы указать, что объект может
сохраняться и восстанавливаться
библиотекой .NET Framework, компилятор добавляет
атрибут Serializable (Преобразуемый в
последовательную форму, упорядочиваемый) к.метаданным
класса Customer (Клиент). Метаданные
представляют собой дополнительную
информацию о программном коде и данных,
которая содержится в самом .NET-приложении.
Метаданные, являющиеся характерным
свойством общеязыковой среды выполнения CLR,
могут содержать также и другую информацию о
коде, включая:
- номер версии и информацию о
местной специфике (регион, язык);
- все используемые типы;
- подробности о каждом типе,
включая его имя. область видимости и т.д.;
- подробную информацию о членах
каждого типа, в частности, используемые
ими методы, сигнатуры методов, и т.д.;
- атрибуты.
Метаданные хранятся вместе с
программным кодом, а не в каком-то
центральном хранилище наподобие
системного реестра в операционной системе
Windows. Способ их хранения не зависит от
используемого языка программирования.
Благодаря всему этому .NET-приложения
содержат самоописания. Во время выполнения
приложения может быть выдан запрос
метаданных с целью получения информации о
коде (например, о наличии или отсутствии
атрибута Serializacle (Преобразуемый в
последовательную форму, упорядочиваемый)).
Вы можете расширить метаданные, дополнив их
своими собственными атрибутами.
В нашем примере библиотека .NET
Framework может запросить метаданные для того,
чтобы получить информацию о структуре
объекта Customer (Клиент), которая затем
используется для сохранения и
восстановления объекта.
|