Страницы

Поиск по вопросам

суббота, 6 июля 2019 г.

Xml-сериализация атрибутов вложенных узлов в свойства объекта

Подскажите пожалуйста, есть ли возможность десериализовать Xml-элемент подобной структуры: в объект примерно такого класса: [XmlRoot("Service")] public class Service { public string Host { get; set; } public string Username { get; set; } public string Password { get; set; } } То есть смысл в том, чтобы не создавать для каждого вложенного узла свой класс, наподобие этого: public class Host { [XmlAttribute("value")] public string Value { get; set; } } и затем не городить огород: [XmlRoot("Service")] public class Service { [XmlElement("Host")] public Host Host { get; set; } . . . }
...
var host = service.Host.Value; Хочется верить, что атрибуты "value" всех вложенных узлов можно сразу замапить на string-свойства. Буду благодарен за любой совет.


Ответ

Может быть, пусть Service имплементирует интерфейс IXmlSerializable и реализует ReadXml разумным образом? Сделать это только при помощи атрибутов невозможно: свойства определяют либо такой: http://domain.com:80 user_name password либо такой синтаксис. Я тут набросал код: [XmlRoot] class Service : IXmlSerializable { string Host; string Username; string Password;
XmlSchema IXmlSerializable.GetSchema() { return null; }
void IXmlSerializable.ReadXml(XmlReader reader) { if (reader.IsEmptyElement) // проверяем формат throw new Exception(); // надо какое-то другое исключение, конечно reader.ReadStartElement(); // читаем открывающий тег Service while (reader.IsStartElement()) // пока есть вложенные теги... processNode(reader); // читаем их reader.ReadEndElement(); // читаем закрывающий тег }
void processNode(XmlReader reader) { if (!reader.IsEmptyElement) // опять проверяем формат throw new Exception(); if (reader.AttributeCount != 1) // то же самое throw new Exception(); string name = reader.Name; string value = reader.GetAttribute(0); setField(name, value); reader.ReadStartElement(); // переходим к следующему }
void setField(string name, string value) { switch (name) // ну или reflection, если хотите { case "Host": Host = value; break; case "Username": Username = value; break; case "Password": Password = value; break; } }
void IXmlSerializable.WriteXml(XmlWriter writer) { serializeField(writer, "Host", Host); serializeField(writer, "Username", Username); serializeField(writer, "Password", Password); }
void serializeField(XmlWriter writer, string name, string value) { writer.WriteStartElement(name); writer.WriteStartAttribute("Value"); writer.WriteString(value); writer.WriteEndElement(); }
}

Комментариев нет:

Отправить комментарий