Для удобного сохранения и извлечения объектов из файлов xml может использоваться класс
XmlSerializer.
Во-первых, XmlSerializer предполагает некоторые ограничения. Например, класс, подлежащий сериализации, должен иметь стандартный конструктор без параметров. Также сериализации подлежат только открытые члены. Если в классе есть поля или свойства с модификатором private, то при сериализации они будут игнорироваться.
Во-вторых, XmlSerializer требует указания типа:
using System;
using System.IO;
using System.Xml.Serialization;
namespace Serialization
{
// класс и его члены объявлены как public
[Serializable]
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
// стандартный конструктор без параметров
public Person()
{ }
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
class Program
{
static void Main(string[] args)
{
// объект для сериализации
Person person = new Person("Tom", 29);
Console.WriteLine("Объект создан");
// передаем в конструктор тип класса
XmlSerializer formatter = new XmlSerializer(typeof(Person));
// получаем поток, куда будем записывать сериализованный объект
using (FileStream fs = new FileStream("persons.xml", FileMode.OpenOrCreate))
{
formatter.Serialize(fs, person);
Console.WriteLine("Объект сериализован");
}
// десериализация
using (FileStream fs = new FileStream("persons.xml", FileMode.OpenOrCreate))
{
Person newPerson = (Person)formatter.Deserialize(fs);
Console.WriteLine("Объект десериализован");
Console.WriteLine($"Имя: {newPerson.Name} --- Возраст: {newPerson.Age}");
}
Console.ReadLine();
}
}
}
Итак, класс Person общедоступный и имеет общедоступные свойства, поэтому он может сериализоваться. При создании объекта XmlSerializer передаем в конструктор тип класса. Метод Serialize добавляет данные в файл persons.xml. А метод Deserialize извлекает их оттуда.
Если мы откроем файл persons.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>29</Age>
</Person>
Равным образом мы можем сериализовать массив или коллекцию объектов, но главное требование состоит в том, чтобы в них был определен стандартный конструктор:
Person person1 = new Person("Tom", 29);
Person person2 = new Person("Bill", 25);
Person[] people = new Person[] { person1, person2 };
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 = (Person[])formatter.Deserialize(fs);
foreach (Person p in newpeople)
{
Console.WriteLine($"Имя: {p.Name} --- Возраст: {p.Age}");
}
}
Но это был простой объект. Однако с более сложными по составу объектами работать так же просто. Например:
using System;
using System.IO;
using System.Xml.Serialization;
namespace Serialization
{
[Serializable]
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Company Company { get; set; }
public Person()
{ }
public Person(string name, int age, Company comp)
{
Name = name;
Age = age;
Company = comp;
}
}
[Serializable]
public class Company
{
public string Name { get; set; }
// стандартный конструктор без параметров
public Company() { }
public Company(string name)
{
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
Person person1 = new Person("Tom", 29, new Company("Microsoft"));
Person person2 = new Person("Bill", 25, new Company("Apple"));
Person[] people = new Person[] { person1, person2 };
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 = (Person[])formatter.Deserialize(fs);
foreach (Person p in newpeople)
{
Console.WriteLine($"Имя: {p.Name} --- Возраст: {p.Age} --- Компания: {p.Company.Name}");
}
}
Console.ReadLine();
}
}
}
Класс 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>29</Age>
<Company>
<Name>Microsoft</Name>
</Company>
</Person>
<Person>
<Name>Bill</Name>
<Age>25</Age>
<Company>
<Name>Apple</Name>
</Company>
</Person>
</ArrayOfPerson>