Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.docx
Скачиваний:
11
Добавлен:
18.08.2019
Размер:
423.24 Кб
Скачать

22. Контракты данных и xml-сериализация

Контракт данных – это тип (класс или структура), объект которого описывает информационный фрагмент. Подразумевается, что этот фрагмент может быть сохранён, а затем восстановлен. Работу с контрактами данных можно рассматривать как один из механизмов сериализации.

Если в качестве контракта данных используется обычный класс, информационный фрагмент образуют открытые поля и свойства класса. Можно пометить тип атрибутом [DataContract]. Тогда информационный фрагмент будут составлять поля и свойства, имеющие атрибут [DataMember]1. Видимость элементов при этом роли не играет.

[DataContract]

public class Student

{

[DataMember]

public string Name { get; set; }

[DataMember]

public double GPA { get; set; }

}

Основным форматом хранения контрактов данных является XML. Поэтому атрибут [DataContract] имеет свойства Name и Namespace для указания имени и пространства имён корневого XML-элемента. У атрибута [DataMember] есть свойство Name, а также свойства Order (порядок записи элементов контракта), IsRequired (обязательный элемент для записи), EmitDefaultValue (нужна ли запись значения по умолчанию для элемента).

[DataContract(Name = "student", Namespace = "bsuir.by")]

public class Student

{

[DataMember(Name = "name", Order = 1)]

public string Name { get; set; }

[DataMember(Name = "gpa", Order = 0)]

public double GPA { get; set; }

}

Если контракт является коллекцией объектов (как класс Group), он маркируется атрибутом [CollectionDataContract]. Кроме этого, для методов контракта данных применимы атрибуты [OnSerializing], [OnSerialized], [OnDeserializing], [OnDeserialized].

Если контракт планируется десериализовать в объекты потомков своего типа, эти потомки должны быть упомянуты при помощи атрибута [KnownType].

[DataContract]

[KnownType(typeof (Postgraduate))]

public class Student { . . . }

public class Postgraduate : Student { . . . }

Для выполнения сериализации контракта данных используются классы:

1. DataContractSerializer – сериализует контракт в формате XML;

2. NetDataContractSerializer – сериализует данные и тип контракта;

3. DataContractJsonSerializer – сериализует контракт в формате JSON.

Рассмотрим пример сериализации контрактов данных:

var student = new Student {Name = "Smirnov", GPA = 9.1};

// конструктор требует указания типа контракта данных

var ds = new DataContractSerializer(typeof (Student));

using (Stream s = File.Create("smirnov.xml"))

{

ds.WriteObject(s, student);

}

// полученный файл smirnov.xml

// <student xmlns="bsuir.by"

// xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

// <gpa>9.1</gpa>

// <name>Smirnov</name>

// </student>

Сериализацию в формате XML можно выполнить при помощи класса XmlSerializer из пространства имён System.Xml.Serialization. При таком подходе сохраняются public-элементы объекта. Кроме этого, тип объекта должен быть открытым и иметь открытый конструктор без параметров.

var student = new Student {Name = "Smirnov", GPA = 9.1};

// при создании XmlSerializer требуется указать сериализуемый тип

var serializer = new XmlSerializer(typeof (Student));

// сериализация

using (Stream stream = File.Create("student.xml"))

{

serializer.Serialize(stream, student);

}

// десериализация

using (Stream stream = File.OpenRead("student.xml"))

{

student = (Student) serializer.Deserialize(stream);

}

Настройка XML-сериализации может быть выполнена при помощи атрибутов. [XmlRoot] применяется к типу и задаёт корневой элемент в XML-файле. При помощи [XmlElement] настраивается имя и пространство имён XML-элемента. [XmlAttribute] используется, если член класса требуется сохранить в виде XML-атрибута. Поля и свойства, которые не должны сохраняться, помечаются атрибутом [XmlIgnore]. Если тип содержит коллекцию объектов, то настройка имени этой коллекции и имени отдельного элемента выполняется при помощи атрибутов [XmlArray] и [XmlArrayItem].

public class Student

{

[XmlAttribute("name")]

public string Name { get; set; }

[XmlIgnore]

public double GPA { get; set; }

}

[XmlRoot("students")]

public class Group

{

[XmlArray("list")]

[XmlArrayItem("student")]

public List<Student> List { get; set; }

}

Отметим, что XML-сериализация не может сохранить коллекции-словари. Если выполняется XML-сериализация объекта, реализующего интерфейс IEnumerable (обычный или универсальный), сохраняются только те элементы, которые доступны через перечислитель.