Учебное пособие (1077022), страница 21
Текст из файла (страница 21)
Файл открывается в режиме чтения с использованием методаFile.OpenRead. После завершения работы с потоком следует закрыть потокс помощью метода Close.ДлядесериализациииспользуетсяметодDeserializeклассаBinaryFormatter, которому в качестве параметра передается открытыйпоток. Этот метод возвращает десериализованный объект в виде объектакласса Object. Затем необходимо привести объект класса Object к нужномутипу, в данном примере к типу DataBin.Результаты вывода в консоль:Бинарная сериализация/десериализацияДо сериализации:str1=строка1 int1=333 double1=123,45После десериализации:str1=строка1 int1=333 double1=123,45Таким образом, объект сначала сериализован в бинарный файл, азатем десериализован из бинарного файла.
Восстановленный объектполностью совпадает с исходным.7.3.2 Сериализация и десериализация в формат XMLДанный вид сериализации и десериализации также используетсядостаточно часто. Принцип его работы практически полностью совпадает с171бинарной сериализацией и десериализацией, только вместо классаBinaryFormatter применяется класс XmlSerializer.Рассмотрим пример сериализации и десериализации в формат XML.Пример класса данных:using System;namespace Serialization{public class DataXml1{public int int1 { get; set; }public double double1 { get; set; }public string str1 { get; set; }public override string ToString(){return"str1=" + str1+ " int1=" + int1.ToString()+ " double1=" + double1.ToString();}}}В случае XML-сериализации атрибут [Serializable] не требуется.Примерсозданияобъектаклассаданных,сериализациидесериализации в формате XML:Console.WriteLine("Сериализация/десериализация в формате XML:");DataXml1 dataXml1 = new DataXml1{str1 = "строка1 xml",int1 = 3333,double1 = 333.33};//+++++++++++++++++//сериализация//+++++++++++++++++Console.WriteLine("До сериализации:");Console.WriteLine(dataXml1);//Формирование имени файлаstring fileXml1Name = Path.Combine(currentPath, "file2.xml");//При сериализации файл необходимо открыть с использованием потоковStream TestFileStream1Xml1 = File.Create(fileXml1Name);//Создание объекта класса сериализациии172XmlSerializer serializerXml1 = new XmlSerializer(typeof(DataXml1));//Cериализация объекта в файлserializerXml1.Serialize(TestFileStream1Xml1, dataXml1);//Закрытие потокаTestFileStream1Xml1.Close();//+++++++++++++++++//десериализация//+++++++++++++++++//Открытие файла в виде потока на чтениеStream TestFileStream2Xml1 = File.OpenRead(fileXml1Name);//Десериализация объектаDataXml1 dataXml1Out =(DataXml1)serializerXml1.Deserialize(TestFileStream2Xml1);//Закрытие потокаTestFileStream2Xml1.Close();Console.WriteLine("После десериализации:");Console.WriteLine(dataXml1Out);Рассмотренный пример практически полностью совпадает с бинарнойсериализацией/десериализацией, за исключением использования классаXmlSerializer.
Конструктор класса XmlSerializer требует передачи вкачествепараметраинформацииотипесериализуемогоклассаtypeof(DataXml1).Результаты вывода в консоль:Сериализация/десериализация в формате XML:До сериализации:str1=строка1 xml int1=3333 double1=333,33После десериализации:str1=строка1 xml int1=3333 double1=333,33Отличие от бинарной сериализации состоит в том, что присериализации формируется не бинарный файл, а файл в формате XML.Содержимое файла file2.xml:<?xml version="1.0"?><DataXml1xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"><int1>3333</int1><double1>333.33</double1><str1>строка1 xml</str1></DataXml1>173ПриXML-сериализациисуществуетвозможностьспомощьюаннотаций для класса и свойств задавать формат сериализации. Изменимкласс данных, добавив аннотации сериализации:using System;using System.Xml.Serialization;namespace Serialization{[XmlRoot(ElementName = "DataXmlWithParameters")]public class DataXml2{[XmlIgnore]public int int1 { get; set; }[XmlAttribute(AttributeName = "DoubleParameter")]public double double1 { get; set; }[XmlElement(ElementName = "StringParameter")]public string str1 { get; set; }public override string ToString(){return"str1=" + str1+ " int1=" + int1.ToString()+ " double1=" + double1.ToString();}}}В данном примере класс помечен аннотацией XmlRoot, в качествепараметра указано имя элемента XML: DataXmlWithParameters.
Свойствоint1 помечено аннотацией XmlIgnore, что отменяет сериализацию данногосвойства. Свойство double1 помечено аннотацией XmlAttribute, поэтомуоно будет сериализовано в виде XML-атрибута с именем DoubleParameter.Свойство str1 будет сериализовано в виде XML-элемента с именем«StringParameter».Содержимое XML-файла для класса DataXml2:<?xml version="1.0"?><DataXmlWithParametersxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"DoubleParameter="333.33"><StringParameter>строка1 xml</StringParameter></DataXmlWithParameters>174Имена всех XML-элементов соответствуют именам, указанным ваннотациях класса DataXml2.
В соответствии с аннотацией, свойствоdouble1 сериализовано в виде атрибута DoubleParameter.Создание объекта класса данных, сериализация и десериализацияпрактически полностью аналогичны предыдущему примеру.ПримерсозданиядесериализациивобъектаформатеклассаXMLсданных,сериализациииспользованиеманнотациисериализации:Console.WriteLine("Сериализация/десериализация в формате XML сатрибутами:");DataXml2 dataXml2 = new DataXml2{str1 = "строка1 xml",int1 = 3333,double1 = 333.33};//+++++++++++++++++//сериализация//+++++++++++++++++Console.WriteLine("До сериализации:");Console.WriteLine(dataXml2);//Формирование имени файлаstring fileXml2Name = Path.Combine(currentPath, "file2atr.xml");//При сериализации файл необходимо открыть с использованием потоковStream TestFileStream1Xml2 = File.Create(fileXml2Name);//Создание объекта класса сериализацииXmlSerializer serializerXml2 = new XmlSerializer(typeof(DataXml2));//Cериализация объекта в файлserializerXml2.Serialize(TestFileStream1Xml2, dataXml2);//Закрытие потокаTestFileStream1Xml2.Close();//+++++++++++++++++//десериализация//+++++++++++++++++//Открытие файла в виде потока на чтениеStream TestFileStream2Xml2 = File.OpenRead(fileXml2Name);//Десериализация объектаDataXml2 dataXml2Out =(DataXml2)serializerXml2.Deserialize(TestFileStream2Xml2);//Закрытие потокаTestFileStream2Xml2.Close();и175Console.WriteLine("После десериализации:");Console.WriteLine(dataXml2Out);Результаты вывода в консоль:Сериализация/десериализация в формате XML с атрибутами:До сериализации:str1=строка1 xml int1=3333 double1=333,33После десериализации:str1=строка1 xml int1=0 double1=333,33Какиожидалось,последесериализациисвойствоint1невосстановлено (по умолчанию имеет значение равное нулю), так какданное свойство в классе данных помечено атрибутом XmlIgnore.7.4 Контрольные вопросы к разделу 71.
Как получить список файлов для заданного каталога?2. Как получить список подкаталогов для заданного каталога?3. Как выполнить чтение текстового файла в виде единой строки?4. Как осуществить запись текстового файла в виде единойстроки?5.
Как реализовать чтение текстового файла в виде массива строк?6. Как осуществить запись текстового файла в виде массива строк?7. Как выполнить сериализацию и десериализацию объекта вбинарный файл?8. Как осуществить сериализацию и десериализацию объекта вXML-файл?9. Как управлять сериализацией и десериализацией объекта вXML-файл с использованием атрибутов?8 РефлексияВ данном разделе рассматриваются основы механизма рефлексии.Рефлексия с одной стороны включает достаточно большое количество176сведений, авторы [1] отмечают, что рефлексии можно посвятитьотдельнуюкнигу.Сдругойстороны,рефлексияоченьширокоиспользуется в современном языке C#.
Выше в пособии рефлексияиспользовалась в большом количестве примеров: для определения типа данных при работе с необобщеннымиколлекциями (работа с типами данных); для сортировки коллекций при проверке того, что тип реализуетинтерфейс IComparable (работа с типами данных); для определения пути к исполняемому файлу (работа сосборками); для бинарной сериализации, когда класс должен быть помеченатрибутом [Serializable] (работа с атрибутами).Фактически работа со сборками, типами данных и атрибутами –основная задача рефлексии.Также следует отметить, что в некоторых книгах термин «рефлексия»(reflection) иногда переводят с английского как «отражение».
Но с такимпереводом трудно согласиться. Дело в том, что данный термин в большейстепенисоответствуетфилософскомутермину«рефлексия».Всоответствии с философским энциклопедическим словарем «рефлексия (отлат. Reflexio – обращение назад) – способность человеческого мышления ккритическому самоанализу». Если спроецировать это определение на языкинформатики, то можно определить рефлексию как способность языкапрограммирования анализировать собственные программы различнымиспособами.Рассмотрим более детально возможности рефлексии в .NET на основефрагментов примера 14.1778.1 Работа со сборкамиКлассы для работы с рефлексией расположены в пространстве именSystem.Reflection.Класс Assembly предназначен для получения информации о сборках.МетодGetExecutingAssemblyвозвращаетинформациюотекущейисполняемой сборке. Также существует группа методов Load* (Load,LoadFile,LoadFrom),позволяющихзагрузитьсборкуиполучитьинформацию о ней.Пример кода, выводящего в консоль информацию о текущей сборке:Console.WriteLine("Вывод информации о сборке:");Assembly i = Assembly.GetExecutingAssembly();Console.WriteLine("Полное имя:" + i.FullName);Console.WriteLine("Исполняемый файл:" + i.Location);Результаты вывода в консоль:Вывод информации о сборке:Полное имя: Reflection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullИсполняемый файл: C:\root\13\Reflection\Reflection\bin\Debug\Reflection.exe8.2 Работа с типами данныхРабота с типами данных один из наиболее часто применяемыхмеханизмов рефлексии.Создадим класс ForInspection, который содержит свойства, методы идругие элементы для получения информации с помощью рефлексии.using System;namespace Reflection{/// <summary>/// Класс для исследования с помощью рефлексии/// </summary>public class ForInspection : IComparable{public ForInspection() { }public ForInspection(int i) { }public ForInspection(string str) { }public int Plus(int x, int y) { return x + y; }178public int Minus(int x, int y) { return x - y; }[NewAttribute("Описание для property1")]public string property1{get { return _property1; }set { _property1 = value; }}private string _property1;public int property2 { get; set; }[NewAttribute(Description = "Описание для property3")]public double property3 { get; private set; }public int field1;public float field2;/// <summary>/// Реализация интерфейса IComparable/// </summary>public int CompareTo(object obj){return 0;}}}Классреализуетконструкторы,методы,интерфейссвойства,IComparable,поляаданных.такжесодержитДляполученияинформации о типе (классе) ForInspection необходимо создать объекткласса Type.Строго говоря, рефлексия не является объектно-ориентрованныммеханизмом.















