Для удобного сохранения и извлечения объектов из файлов xml может использоваться класс XmlSerializer
из пространства имен System.Xml.Serialization
. Данный класс упрощает сохранение сложных объектов в формат xml и последующее их извлечение.
Для создания объекта XmlSerializer можно применять различные конструкторы, но почти все они требуют указания типа данных, которые будут сериализоваться и десериализоваться:
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person)); //[Serializable] class Person { }
В данном случае XmlSerializer будет работать только с объектами класса Person.
Следует учитывать, что XmlSerializer предполагает некоторые ограничения. Например, класс, подлежащий сериализации, должен иметь стандартный конструктор
без параметров и должен иметь модификатор доступа public. Также сериализации подлежат только открытые члены.
Если в классе есть поля или свойства с модификатором private
, то при сериализации они будут игнорироваться. Кроме того, свойства должны иметь общедоступные геттеры и сеттеры.
Для сериализации (то есть сохранения в форма xml) применяется метод Serialize(). Данный метод имеет ряд версий. Возьмем самую простую из них:
void Serialize (Stream stream, object? o);
В качестве первого параметра передается поток Stream (например, объект FileStream), в который будет идти сериализация. А второй параметр представляет собственно тот объект, который будет сохраняться в формат xml. Например:
using System.Xml.Serialization; // объект для сериализации Person person = new Person("Tom", 37); // передаем в конструктор тип класса Person XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person)); // получаем поток, куда будем записывать сериализованный объект using (FileStream fs = new FileStream("person.xml", FileMode.OpenOrCreate)) { xmlSerializer.Serialize(fs, person); Console.WriteLine("Object has been serialized"); } //[Serializable] public class Person { public string Name { get; set; } = "Undefined"; public int Age { get; set; } = 1; public Person() { } public Person(string name, int age) { Name = name; Age = age; } }
Итак, класс Person общедоступный, имеет общедоступные свойства и конструктор без параметров, поэтому объекты этого класса подлежат сериализации. При создании объекта XmlSerializer передаем в конструктор тип класса Person.
В метод Serialize передается файловый поток для сохранения данных в файл person.xml и сохраняемый в этот файл объект Person. И если по завершению программы мы откроем файл person.xml, то увидим содержание нашего объекта:
<?xml version="1.0"?> <Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Name>Tom</Name> <Age>37</Age> </Person>
Для десериализации данных xml в объект кода C# применяется метод Deserialize(). Отметим одну из версий этого метода:
object? Deserialize (Stream stream);
В качестве параметра в метод передается объект Stream, который содержит данные в формате xml. Результатом метода является десериализованный объект.
Например, десериализуем данные из выше созданного файла person.xml:
using System.Xml.Serialization; XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person)); // десериализуем объект using (FileStream fs = new FileStream("person.xml", FileMode.OpenOrCreate)) { Person? person = xmlSerializer.Deserialize(fs) as Person; Console.WriteLine($"Name: {person?.Name} Age: {person?.Age}"); } public class Person { public string Name { get; set; } = "Undefined"; public int Age { get; set; } = 1; public Person() { } public Person(string name, int age) { Name = name; Age = age; } }
Подобным образом мы можем сериализовать массив или коллекцию объектов:
using System.Xml.Serialization; Person[] people = new Person[] { new Person("Tom", 37), new Person("Bob", 41) }; XmlSerializer formatter = new XmlSerializer(typeof(Person[])); // сохранение массива в файл using (FileStream fs = new FileStream("people.xml", FileMode.OpenOrCreate)) { formatter.Serialize(fs, people); } // восстановление массива из файла using (FileStream fs = new FileStream("people.xml", FileMode.OpenOrCreate)) { Person[]? newpeople = formatter.Deserialize(fs) as Person[]; if(newpeople != null) { foreach (Person person in newpeople) { Console.WriteLine($"Name: {person.Name} --- Age: {person.Age}"); } } } public class Person { public string Name { get; set; } = "Undefined"; public int Age { get; set; } = 1; public Person() { } public Person(string name, int age) { Name = name; Age = age; } }
Консольный вывод:
Name: Tom --- Age: 37 Name: Bob --- Age: 41
Но это был простой объект. Однако с более сложными по составу объектами работать так же просто. Например:
using System.Xml.Serialization; var microsoft = new Company("Microsoft"); var google = new Company("Google"); Person[] people = new Person[] { new Person("Tom", 37, microsoft), new Person("Bob", 41, google) }; XmlSerializer formatter = new XmlSerializer(typeof(Person[])); using (FileStream fs = new FileStream("people.xml", FileMode.OpenOrCreate)) { formatter.Serialize(fs, people); } using (FileStream fs = new FileStream("people.xml", FileMode.OpenOrCreate)) { Person[]? newpeople = formatter.Deserialize(fs) as Person[]; if(newpeople != null) { foreach (Person person in newpeople) { Console.WriteLine($"Name: {person.Name}"); Console.WriteLine($"Age: {person.Age}"); Console.WriteLine($"Company: {person.Company.Name}"); } } } public class Company { public string Name { get; set; } = "Undefined"; // стандартный конструктор без параметров public Company() { } public Company(string name) => Name = name; } public class Person { public string Name { get; set; } = "Undefined"; public int Age { get; set; } = 1; public Company Company { get; set; } = new Company(); public Person() { } public Person(string name, int age, Company company) { Name = name; Age = age; Company = company; } }
Класс Person содержит свойство Company, которое будет хранить объект класса Company. Члены класса Company объявляются с модификатором public, кроме того также присутствует стандартный конструктор без параметров. В итоге после сериализации мы получим следующий xml-документ:
<?xml version="1.0"?> <ArrayOfPerson xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Person> <Name>Tom</Name> <Age>37</Age> <Company> <Name>Microsoft</Name> </Company> </Person> <Person> <Name>Bob</Name> <Age>41</Age> <Company> <Name>Google</Name> </Company> </Person> </ArrayOfPerson>