Я отримую xml від третьої сторони, і мені потрібно десеріалізувати його в об’єкт C #. Цей xml може містити атрибути зі значенням цілочисельного типу або порожнім значенням: attr = ”11” або attr = ””. Я хочу десеріалізувати це значення атрибута у властивості з типом цілого числа, що обнуляється. Але XmlSerializer не підтримує десеріалізацію для типів, що дозволяють обнуляти. Наступний тестовий код не вдається під час створення XmlSerializer з InvalidOperationException {"Сталася помилка, що відображає тип 'TestConsoleApplication.SerializeMe'."}.
[XmlRoot("root")]
public class SerializeMe
{
[XmlElement("element")]
public Element Element { get; set; }
}
public class Element
{
[XmlAttribute("attr")]
public int? Value { get; set; }
}
class Program {
static void Main(string[] args) {
string xml = "<root><element attr=''>valE</element></root>";
var deserializer = new XmlSerializer(typeof(SerializeMe));
Stream xmlStream = new MemoryStream(Encoding.ASCII.GetBytes(xml));
var result = (SerializeMe)deserializer.Deserialize(xmlStream);
}
}
Коли я змінюю тип властивості 'Value' на int, десеріалізація не вдається з InvalidOperationException:
У документі XML є помилка (1, 16).
Хтось може порадити, як десериалізувати атрибут з порожнім значенням у типовий тип (як нульовий), одночасно десеріалізуючи непусте значення атрибута в ціле число? Чи є якась хитрість для цього, тому мені не доведеться виконувати десеріалізацію кожного поля вручну (насправді їх дуже багато)?
Оновлення після коментаря від ahsteele:
-
Наскільки мені відомо, цей атрибут працює лише з XmlElementAttribute - цей атрибут вказує, що елемент не має вмісту, будь то дочірні елементи або основний текст. Але мені потрібно знайти рішення для XmlAttributeAttribute. У будь-якому випадку я не можу змінити xml, оскільки я не маю над ним контролю.
-
Ця властивість працює лише тоді, коли значення атрибута не є порожнім або коли атрибут відсутній. Коли attr має порожнє значення (attr = ''), конструктор XmlSerializer не працює (як очікувалося).
public class Element { [XmlAttribute("attr")] public int Value { get; set; } [XmlIgnore] public bool ValueSpecified; }
Спеціальний клас Nullable, як у цьому дописі блогу Алекса Скорделліса
Я спробував прийняти клас із цього допису в блозі до своєї проблеми:
[XmlAttribute("attr")] public NullableInt Value { get; set; }
Але конструктор XmlSerializer не працює з InvalidOperationException:
Не вдається серіалізувати член "Значення" типу TestConsoleApplication.NullableInt.
XmlAttribute / XmlText не можна використовувати для кодування типів, що реалізують IXmlSerializable}
Потворне сурогатне рішення (соромно за те, що я написав цей код тут :)):
public class Element { [XmlAttribute("attr")] public string SetValue { get; set; } public int? GetValue() { if ( string.IsNullOrEmpty(SetValue) || SetValue.Trim().Length <= 0 ) return null; int result; if (int.TryParse(SetValue, out result)) return result; return null; } }
Але я не хочу придумувати таке рішення, оскільки воно порушує інтерфейс мого класу для своїх споживачів. Я б краще реалізував інтерфейс IXmlSerializable вручну.
На даний момент, схоже, я повинен впровадити IXmlSerializable для всього класу Element (він великий), і немає простих обхідних шляхів ...