Как сделать тип значения nullable с помощью .NET XmlSerializer?
Предположим, у меня есть этот объект:
[Serializable] public class MyClass { public int Age { get; set; } public int MyClassB { get; set; } } [Serializable] public class MyClassB { public int RandomNumber { get; set; } }
XmlSerializer сериализует объект следующим образом:
0 4234
Как я могу присвоить свойство Age nullable? IE: не сериализовать свойство Age, когда оно меньше 0?
- Как XML-сериализовать словарь
- Когда class унаследован от List , XmlSerializer не сериализует другие атрибуты
- Сериализация объекта в строку
- XmlSerializer сериализует общий список интерфейса
- Сериализация Nullable в XML
Я попытался с Nullable, но он сериализовал мой объект следующим образом:
4234
Прочитав документацию MSDN, я нашел следующее:
Вы не можете применить свойство IsNullable к члену, введенному как тип значения, потому что тип значения не может содержать нулевую ссылку nullNothingnullptra (Nothing в Visual Basic). Кроме того, вы не можете установить для этого свойства значение false для типов значений с нулевым значением. Когда такие типы имеют нулевую ссылку nullNothingnullptra (Nothing в Visual Basic), они будут сериализованы, установив xsi: nil в true.
source: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlelementattribute.isnullable.aspx
Я понимаю, что тип значения не может иметь значение null. Тип valuetype всегда настроен на что-то. Сериализация не может принять решение о ее сериализации или нет на основе ее текущего значения.
Я пробовал с атрибутами, но это не сработало. Я попытался создать объект agecontainer и манипулировать его сериализацией с атрибутами, но это не сработало.
Я действительно хочу:
4234
Когда свойство Age меньше 0 (ноль).
Похоже, вам придется внедрять пользовательскую сериализацию.
Да, это то, что я тоже, но я бы хотел уйти без него.
В приложении объект намного сложнее, и я бы не хотел сам обрабатывать сериализацию.
- Предотrotation изменения часового пояса при десериализации значения DateTime
- Каков наилучший способ анализа (большого) XML в коде C #?
- Преобразование набора данных в XML
- «Тип не ожидается», используя DataContractSerializer - но это просто class, не смешные вещи?
- Сериализация XML XML без текстового объявления
- JAXB Отображение циклических ссылок на XML
- JAXB: Как игнорировать пространство имен во время развязывания XML-документа?
- Каковы различия между XmlSerializer и BinaryFormatter
Я только что обнаружил это. XmlSerialier
ищет XXXSpecified
типа XXXSpecified
чтобы определить, следует ли ее включить. Это должно решить проблему красиво.
[Serializable] public class MyClass { public int Age { get; set; } [XmlIgnore] public bool AgeSpecified { get { return Age >= 0; } } public int MyClassB { get; set; } } [Serializable] public class MyClassB { public int RandomNumber { get; set; } }
Доказательство:
static string Serialize(T obj) { var serializer = new XmlSerializer(typeof(T)); var builder = new StringBuilder(); using (var writer = new StringWriter(builder)) { serializer.Serialize(writer, obj); return builder.ToString(); } } static void Main(string[] args) { var withoutAge = new MyClass() { Age = -1 }; var withAge = new MyClass() { Age = 20 }; Serialize(withoutAge); // = 0 Serialize(withAge); // = 20 0 }
Изменить : Да, это документированная функция. См. Запись MSDN для XmlSerializer
Другой вариант – использовать специальный шаблон для создания логического поля, распознаваемого XmlSerializer, и применить XmlIgnoreAttribute к полю. Шаблон создается в виде свойстваNameSpecified. Например, если есть поле с именем «MyFirstName», вы также создадите поле с именем «MyFirstNameSpecified», которое инструктирует XmlSerializer о том, следует ли генерировать XML-элемент с именем «MyFirstName».
Расширение ответа Сэмюэля и комментарий Грега Бича к случаю логического свойства: если свойство имеет тип bool, вы не можете написать простой тест в свойстве propertySpecified.
Решением является использование типа Nullable
using System.Xml.Serialization; public class Person { public bool? Employed { get; set; } [XmlIgnore] public bool EmployedSpecified { get { return Employed.HasValue; } } }
Альтернативой использованию типа nullable для числового свойства (предложенного Грегом Биком) является установка свойства value недопустимым значением по умолчанию, например -1, следующим образом:
using System.ComponentModel; using System.Xml.Serialization; public class Person { [DefaultValue(-1)] public int Age { get; set; } [XmlIgnore] public bool AgeSpecified { get { return Age >= 0; } } }
Вы можете использовать XmlElementAttribute.IsNullable :
[Serializable] public class MyClass { [XmlElement(IsNullable = true)] public int? Age { get; set; } public int MyClassB { get; set; } }
Это должно помочь Make Age int? а также..
public bool ShouldSerializeAge() { return Age.HasValue; }
.. это означает добавление методов ShouldSerializeXXX в ваш class!
Забудьте о Nullable … ShouldSerializeXXX – довольно приемлемое решение. Здесь возраст будет сериализован по вашему состоянию.
[Serializable] public class MyClass { public int Age { get; set; } public int MyClassB { get; set; } #region Conditional Serialization public bool ShouldSerializeAge() { return age > 0; } #endregion } [Serializable] public class MyClassB { public int RandomNumber { get; set; } }
xsd.exe будет автогенерировать свойство XXXSpecified и accessors, если вы установите атрибут minoccurs как ‘minoccurs = “0” для элемента … если вы используете схему для определения своего xml / class