2013-04-23 2 views
1

У меня есть класс, который используется для Xml Serialization.Как игнорировать свойство nullable из сериализации, если оно пустое или пустое?

, внутри которого у меня есть обнуляемое имущество, украшенная XmlAttribute:

[XmlAttribute("lastUpdated")] 
public DateTime? LastUpdated { get; set; } 

Как игнорировать свойство из сериализации, если он пустой или пустой?

Я пробовал ниже, но это не сериализации, когда есть значение (всегда игнорирует):

[XmlIgnore] 
     public DateTime? LastUpdatedValue { get; set; } 

     [XmlAttribute("lastUpdated")] 
     public DateTime LastUpdated { get; set; } 

     public bool ShouldSerializeLastUpdated() 
     { 
      return LastUpdatedValue.HasValue; 
     } 
+5

Вы видели это http://stackoverflow.com/questions/244953/serialize-a-nullable-int?rq=1 – Yahya

+0

Что вы ожидаете XML выглядеть? В этом случае вы получите '', если свойство равно null; вы можете либо выполнить пост-процесс xml (проще), либо написать класс XmlWriter (сложнее, работает лучше). Существуют и другие варианты, которые являются сложными и раздувают ваш код. –

+0

no Я просто хочу игнорировать xmlattribute, если он равен нулю. но DateTime? не является сериализуемым. Как его заменить? –

ответ

6

Nullable не поддерживается непосредственно XmlSerialization.

Если вы хотите использовать свойство nullable, вы должны использовать свойство non nullable и добавить свойство boolean с тем же именем свойства с суффиксом «Specified», который указывает, когда свойство должно быть сериализуемым.

Пример с вашим делом:

private DateTime? _lastUpdated; 

    [XmlAttribute("lastUpdated")] 
    public DateTime LastUpdated { 
     get { 
      return (DateTime)_lastUpdated; 
     } 
     set 
     { 
      _lastUpdated = value; 
     } 
    } 

    public bool LastUpdatedSpecified 
    { 
     get 
     { 
      return _lastUpdated.HasValue; 
     } 
    } 
+0

Спасибо, но проблема в том, что я больше не могу сериализовать его с помощью XmlSerializer. Я получаю эту ошибку: + \t \t InnerException \t {"Произошла ошибка, отражающая свойство LastUpdated."} \t System.Exception {System.InvalidOperationException} –

+0

Извините, я слишком быстро исправил и редактировал свой код. Можете ли вы попробовать это? – binard

+0

@ TheLight вы можете принять мой ответ, как лучший ответ? – binard

2

Вы можете использовать XmlElementAttribute.IsNullable:

[Serializable] 
public class Result 
{ 
    [XmlElement(IsNullable = true)] 
    public DateTime? LastUpdated { get; set; } 
} 
+0

Невозможно использовать атрибуты. Он используется только для элементов. – belurd

2

Я знаю, что эта тема стара. Это решение, с которым я пришел. Класс, который инкапсулирует тип и имеет неявное литье к типу. При сериализации переменная-член может быть помечена IsNullable = false без ошибок компилятора и блокирования ее от сериализации при нулевом значении.

public class Optional<T> where T : struct, IComparable 
{ 
    public Optional(T valueObject) 
    { 
     Value = valueObject; 
    } 

    public Optional() 
    { 
    } 

    [XmlText] 
    public T Value { get; set; } 

    public static implicit operator T(Optional<T> objectToCast) 
    { 
     return objectToCast.Value; 
    } 

    public static implicit operator Optional<T>(T objectToCast) 
    { 
     return new Optional<T>(objectToCast); 
    } 
} 

Затем использовать его в своем классе

[Serializable] 
[XmlRoot(ElementName = "foo")] 
public class foo 
{ 
    [XmlElement(ElementName = "myInteger", isNullable = false)] 
    Optional<int> myInt; 
} 

Вы можете сделать такие вещи, как

 myFoo.myInt = 7; 
     int j = 8 + myFoo.myInt; 

Для всех целей Это внутр. Для целей сериализации он может быть пустым и заблокирован от сериализации.

1

Это работает для меня.

[XmlIgnore] 
    public float? Speed { get; set; } 

    [XmlAttribute("Speed")] 
    public float SpeedSerializable 
    { 
     get 
     { 
      return this.Speed.Value; 
     } 
     set { this.Speed = value; } 
    } 

    public bool ShouldSerializeSpeedSerializable() 
    { 
      return Speed.HasValue; 
    } 
+0

Это отлично работает для меня. Благодаря! – JohnW

0

Примечание: Это точно работает в контрактах SOAP в WCF. Я не тестировал другие сценарии сериализации Xml.

При использовании [DataContract] вы можете использовать

[DataMember(EmitDefaultValue = false)]

  • Для boolean он будет издавать только значение, если оно true.
  • Для nullable boolean он будет испускать, если это не null.
  • Для string он будет выдавать только значение, если оно не null.
  • Для int он выдает только значение, если оно не 0.

т.д.

Убедитесь поставить [DataContract] на сам класс и [DataMember] всех членов, которые вы хотите сериализации ли вы указываете EmitDefaultValue или нет.

Setting the EmitDefaultValue property to false is not a recommended practice. It should only be done if there is a specific need to do so (such as for interoperability or to reduce data size).

https://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.emitdefaultvalue(v=vs.110).aspx

Смежные вопросы