# 000160. Сериализация и десериализация XML в c\#

Сериализация и десериализация XML в c#||wmysterio|wmysterio|<wmysterio@yandex.ru>|||Доброго времени суток всем пользователям нашего сайта! Сегодня мы изучим одну важную тему как сериализация и обратный её процесс - десириализация. Под этим странным словом "сериализация" скрывается процесс перевода некой информации в поток битов с целью сохранить где-то или восстановить из чего-то. Иными словами - изъять из файла объект или сохранить объект в файл. Для примера мы будем использовать XML-файл для хранения нашего субъекта. Сам объект будет представлен следующим классом, например:<br>

Кодpublic class Car {\
&#x20;   public float Speed;\
&#x20;   public string EngineType;\
&#x20;   public int SeatCount;\
\
&#x20;   public Car() { }\
}Чтобы удобно работать с таким средством, как сериализация, Нам лучше создать ещё один класс, который будет выполнять поставленную задачу. К примеру, назовём его "XMLFile". Чтобы он умел работать со всеми типами данных, ему нужно указать приставку с типом данных на вход:\
Кодpublic class XMLFile\*\*\<T>\*\* {\
\
}Как правило неизвестный тип(или ожидаемый) принято называть как **T**, хотя это никак не влияет общую картину. Так как этот тип нам нужно использовать в методах, которые я запланировал, нам нужно создать поле со стандартным типом **Type**, переменная которой будет заполнятся из конструктора с помощью инструкции typeof, которая как раз и возвращает тип переданного в неё объекта. Что Нам ещё нужно? Естественно - это путь к файлу, иначе куда/откуда будет записывать/читать класс. Наш конструктор будет иметь следующий вид:\
Кодpublic class XMLFile\*\*\<T>\*\* {\
&#x20;  Type dataType;\
&#x20;  string filePath;\
\
&#x20;  public XMLFile( string filePath ) {\
&#x20;     this.filePath = filePath + ".xml";\
&#x20;     dataType = typeof( T );\
&#x20;  }\
}Дальше нам нужно написать две процедуры, которые сериализуют и десириализуют объект соответственно. Первый метод назовём - **Load()**, который десериализует данные из файла и вернёт объект указанного в конструкторе типа.\
\
Стандартный класс **XmlSerializer может получать данные только с потоковыми типами данных, например TextReader или TextWriter, по-этому мы должны создать объект потоковых типов а затем сам десериалайзер:**\
**КодTextReader tr = new StreamReader( filePath ); // открываем поток**\
**XmlSerializer reader = new XmlSerializer( dataType ); // передаём тип T в качестве параметра**\
**Следующим щагом будет создания объекта типа T** и возврат его из метода. Делается это следующим образом:\
Кодreader.Deserialize( tr );\
Как только данные изъяты нам нужно преобразовать его к типу **T**, чтобы наш c# умел с ним обращаться. Наш метод будет таков:\
Кодpublic **T** Load() {\
&#x20;  TextReader tr = new StreamReader( filePath );\
&#x20;  XmlSerializer reader = new XmlSerializer( dataType );\
&#x20;  **T** **instance** = ( **T** ) reader.Deserialize( tr );\
&#x20;  tr.Close(); // обязательно нужно закрывать файловый поток!\
&#x20;  return **instance**;\
}\
Сохранение происходит несколько иным образом, но за похожим принципом. Во-первых: нужно знать объект, который нужно сохранить, по-этому передаём его в качестве параметра процедуры через ключевое слово object. Во-вторых: в качестве файлового потока используем TextWriter, так как мы должны записывать данные.  Для сериализации используем следующий код:\
Кодpublic void Save( object Obj ) {\
&#x20;  TextWriter tw = new StreamWriter( filePath );\
&#x20;  XmlSerializer writer = new XmlSerializer( dataType );\
&#x20;  writer.Serialize( tw, **Obj** );\
&#x20;  tw\.Close();\
}\
Важно! Как уже было сказано, сериализация происходит только с публичными полями. Это значит, что все методы и приватные поля не будут входить в сохраняемый объект.\
\
Наш класс XMLFile иметь такое содержание:\
Кодpublic class XMLFile\<T> {\
&#x20;  Type dataType;\
&#x20;  string filePath;\
\
&#x20;  public XMLFile( string filePath ) {\
&#x20;     this.filePath = filePath + ".xml";\
&#x20;     dataType = typeof( T );\
&#x20;  }\
\
&#x20;  public T Load() {\
&#x20;     TextReader tr = new StreamReader( filePath );\
&#x20;     XmlSerializer reader = new XmlSerializer( dataType );\
&#x20;     T instance = (T) reader.Deserialize( tr );\
&#x20;     tr.Close();\
&#x20;     return instance;\
&#x20;  }\
\
&#x20;  public void Save( object Obj ) {\
&#x20;     TextWriter tw = new StreamWriter( filePath );\
&#x20;     XmlSerializer writer = new XmlSerializer( dataType );\
&#x20;     writer.Serialize( tw, Obj );\
&#x20;     tw\.Close();\
&#x20;  }\
\
}\
Давайте проверим рабоспособность нашего класса. Для этого создадим объект класса Car, который мы написали выше и сохраним его. Наш код будет следующим:\
Код   static void Main( string\[] args ) {\
&#x20;     XMLFile\<Car> file = new XMLFile\<Car>( "save" ); // создаём объект.\
\
&#x20;     Car c = new Car(); // создаём авто и заполняем поля объекта\
&#x20;     c.EngineType = "auto";\
&#x20;     c.SeatCount = 4;\
&#x20;     c.Speed = 25.0f;\
\
&#x20;     file.Save( c ); // сохраняем транспорт\
&#x20;  }\
Проверяем результат:\
[![](https://github.com/wmysterio/scm-scripting-lessons/blob/main/_pu/2/s06072255.jpg)](https://github.com/wmysterio/scm-scripting-lessons/blob/main/_pu/2/06072255.png)\
\
Как мы видим - наш файл преобразовал некое дерево (как обычный xml-документ). Атрибуты "xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>" xmlns:xsd="<http://www.w3.org/2001/XMLSchema>"" можно удалить. Они никак не будут влиять на чтение объекта. Это чтение мы сейчас сделаем, используя следующий код:\
Код   static void Main( string\[] args ) {\
&#x20;     XMLFile\<Car> file = new XMLFile\<Car>( "save" );\
&#x20;     Car c = file.Load(); // получаем объект из файла\
&#x20;     // и выводим информацию об объекте\
&#x20;     Console.WriteLine( "Engine: {0}\nSeat count: {1}\nMax. speed: {2}", c.EngineType, c.SeatCount, c.Speed );\
&#x20;     Console.ReadKey();\
&#x20;  }\
Результат:\
![](https://github.com/wmysterio/scm-scripting-lessons/blob/main/_pu/2/32790903.png)\
\
Дальше в уроке пойдёт речь о некоторых особенностях заполнения xml-документа. В первую очередь это касается списков и массивов. Если наш класс Car будет иметь поле\
Кодpublic List\<string> Author;\
то в таком формате нужно указывать тип, который указан в скобках:\
Код\<Car>\
&#x20; **\<Author>**\
&#x20;   **\<string>Joe MC Dolls\</string>**\
&#x20;   **\<string>El Bolder\</string>**\
&#x20;   **\<string>Mac Todds\</string>**\
&#x20;   **\<string>Jeck Petterson\</string>**\
&#x20;   **\<string>Yang Jedd\</string>**\
&#x20;   **\<string>Poly Ennson\</string>**\
&#x20; **\</Author>**\
&#x20; \<Speed>25\</Speed>\
&#x20; \<EngineType>auto\</EngineType>\
&#x20; \<SeatCount>4\</SeatCount>\
\</Car>\
Второй случай будет касаться массивов. Заполнение не отличаются от списков, но в качестве примера возьмём класс **Car**. Содержимое xml-файла с полем\
Кодpublic Car\[] Cars;\
в классе, например **Test**,будет таковым:\
Код\<Test>\
&#x20; **\<Cars>**\
&#x20;   **\<Car>**\
&#x20;     **\<Speed>25\</Speed>**\
&#x20;     **\<EngineType>auto\</EngineType>**\
&#x20;     **\<SeatCount>4\</SeatCount>**\
&#x20;   **\</Car>**\
&#x20;   **\<Car>**\
&#x20;     **\<Speed>120\</Speed>**\
&#x20;     **\<EngineType>auto\</EngineType>**\
&#x20;     **\<SeatCount>2\</SeatCount>**\
&#x20;   **\</Car>**\
&#x20;   **\<Car>**\
&#x20;     **\<Speed>400\</Speed>**\
&#x20;     **\<EngineType>auto\</EngineType>**\
&#x20;     **\<SeatCount>1\</SeatCount>**\
&#x20;   **\</Car>**\
&#x20; **\</Cars>**\
\</Test>\
Некоторые типы данный нельзя сохранить. Кроме этого, сложные двухмерные массивы или списки имеют другие конструкции. Например: поле\
Кодpublic List\<List\<string>> Autors;как правило заполняется следующим образом:\
Код\<Autors>\
&#x20; \<ArrayOfString>\
&#x20;   \<string>test 0 1\</string>\
&#x20;   \<string>test 0 2\</string>\
&#x20;   \<string>test 0 3\</string>\
&#x20; \</ArrayOfString>\
&#x20; \<ArrayOfString />\
&#x20;   \<string>test 1 1\</string>\
&#x20;   \<string>test 1 2\</string>\
&#x20;   \<string>test 1 3\</string>\
&#x20; \<ArrayOfString />\
\</Autors>\
По-этому, если Вы решились заполнить XML-файл вручную, то лучше сохранить заранее объект а выходной документ использовать в качестве примера для Вашего файла.\
\
Ещё несколько слов о требованию игнорировать некие поля. Как правило игнорируются приватные поля а также те, которые не указаны в XML-файле. Вот простой пример:\
Код\[XmlIgnore]\
public Car Preview;\
\[XmlIgnore]\
string Pattern;\
Нужно немного потренироваться, ничего сложного здесь нет. С Вами был wmysterio. До встречи в новых уроках.\
|3685|1|0|06072255`png`900`146`400`64\|32790903`png`158`123||serializacija\_i\_deserializacija\_xml\_v\_c|1400678655


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lessons.sannybuilder.com/00300/00100/000160.-serializaciya-i-deserializaciya-xml-v-c.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
