Как сделать тип значения 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?

Я попытался с 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 (ноль).


Похоже, вам придется внедрять пользовательскую сериализацию.

Да, это то, что я тоже, но я бы хотел уйти без него.

В приложении объект намного сложнее, и я бы не хотел сам обрабатывать сериализацию.

Я только что обнаружил это. 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); // = 200 } 

Изменить : Да, это документированная функция. См. Запись MSDN для XmlSerializer

Другой вариант – использовать специальный шаблон для создания логического поля, распознаваемого XmlSerializer, и применить XmlIgnoreAttribute к полю. Шаблон создается в виде свойстваNameSpecified. Например, если есть поле с именем «MyFirstName», вы также создадите поле с именем «MyFirstNameSpecified», которое инструктирует XmlSerializer о том, следует ли генерировать XML-элемент с именем «MyFirstName».

Расширение ответа Сэмюэля и комментарий Грега Бича к случаю логического свойства: если свойство имеет тип bool, вы не можете написать простой тест в свойстве propertySpecified.

Решением является использование типа Nullable , тогда тест в свойстве propertySpecified является просто property.HasValue. например

 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

  • ShouldSerialize * () vs * Условный шаблон условной сериализации
  • Interesting Posts
    Давайте будем гением компьютера.