2008-10-28 31 views
81

我有一個可空的int類嗎?數據類型設置爲序列化爲xml元素。有沒有什麼辦法來設置它,所以如果值爲null,xml序列化程序將不會序列化元素?我嘗試添加[System.Xml.Serialization.XmlElement(IsNullable = false)]屬性,但我得到一個運行時序列化異常說有一個錯誤反映了類型,因爲「IsNullable可能不是對Nullable類型設置爲'false'。考慮使用'System.Int32'類型或從XmlElement屬性中刪除IsNullable屬性。「序列化一個空的int

[Serializable] 
[System.Xml.Serialization.XmlRoot("Score", Namespace = "http://mycomp.com/test/score/v1")] 
public class Score 
{ 
    private int? iID_m; 
    ... 

    /// <summary> 
    /// 
    /// </summary>   
    public int? ID 
    { 
     get 
     { 
      return iID_m; 
     } 
     set 
     { 
      iID_m = value; 
     } 
    } 
    ... 
} 

上面的類將序列化到:

<Score xmlns="http://mycomp.com/test/score/v1"> 
    <ID xsi:nil="true" /> 
</Score> 

但對那些空我不想ID元素可言,主要是因爲當我在MSSQL使用OPENXML的ID,它返回對於看起來像

回答

139

XmlSerializer的支持ShouldSerialize{Foo}()模式,這樣你就可以添加一個方法:

public bool ShouldSerializeID() {return ID.HasValue;} 

也有{Foo}Specified模式 - 不知道的XmlSerializer支持的那一個。

+8

XmlSerializer也支持[Foo}指定模式。 – 2009-03-04 13:47:13

+23

相關頁面位於:http://msdn.microsoft.com/en-us/library/53b8022e%28VS.71%29.aspx – cbp 2010-01-08 06:31:43

+1

任何方式使用ShouldSerialize 與自動生成的屬性?即沒有局部變量。 – Jay 2010-07-15 15:20:14

1

的元素,0代替null對於XmlElementAttribute.IsNullable,不幸的是,您描述的行爲在文檔中被準確記錄。

12

我想出了一個利用兩個屬性的解決方法。一個int?屬性與一個XmlIgnore屬性和一個被序列化的對象屬性。

/// <summary> 
    /// Score db record 
    /// </summary>   
    [System.Xml.Serialization.XmlIgnore()] 
    public int? ID 
    { 
     get 
     { 
      return iID_m; 
     } 
     set 
     { 
      iID_m = value; 
     } 
    } 

    /// <summary> 
    /// Score db record 
    /// </summary>   
    [System.Xml.Serialization.XmlElement("ID",IsNullable = false)] 
    public object IDValue 
    { 
     get 
     { 
      return ID; 
     } 
     set 
     { 
      if (value == null) 
      { 
       ID = null; 
      } 
      else if (value is int || value is int?) 
      { 
       ID = (int)value; 
      } 
      else 
      { 
       ID = int.Parse(value.ToString()); 
      } 
     } 
    } 
+0

該解決方案非常棒,因爲它還允許將NULL編碼爲客戶端的「佔位符」值,該值無法識別ints中的NULL,即Flex。 – 2013-06-25 09:01:12

6

哇謝謝這個問題/答案真的幫了我。我心臟Stackoverflow。

我讓你在做的事情上面更通用一些。我們真正想要的是讓Nullable具有稍微不同的序列化行爲。我使用Reflector構建自己的Nullable,並在這裏和那裏添加了一些內容,以使XML序列化以我們想要的方式工作。似乎工作得很好:

public class Nullable<T> 
{ 
    public Nullable(T value) 
    { 
     _value = value; 
     _hasValue = true; 
    } 

    public Nullable() 
    { 
     _hasValue = false; 
    } 

    [XmlText] 
    public T Value 
    { 
     get 
     { 
      if (!HasValue) 
       throw new InvalidOperationException(); 
      return _value; 
     } 
     set 
     { 
      _value = value; 
      _hasValue = true; 
     } 
    } 

    [XmlIgnore] 
    public bool HasValue 
     { get { return _hasValue; } } 

    public T GetValueOrDefault() 
     { return _value; } 
    public T GetValueOrDefault(T i_defaultValue) 
     { return HasValue ? _value : i_defaultValue; } 

    public static explicit operator T(Nullable<T> i_value) 
     { return i_value.Value; } 
    public static implicit operator Nullable<T>(T i_value) 
     { return new Nullable<T>(i_value); } 

    public override bool Equals(object i_other) 
    { 
     if (!HasValue) 
      return (i_other == null); 
     if (i_other == null) 
      return false; 
     return _value.Equals(i_other); 
    } 

    public override int GetHashCode() 
    { 
     if (!HasValue) 
      return 0; 
     return _value.GetHashCode(); 
    } 

    public override string ToString() 
    { 
     if (!HasValue) 
      return ""; 
     return _value.ToString(); 
    } 

    bool _hasValue; 
    T _value; 
} 

你失去了你的成員爲int的能力?等等(必須改用空值<int>),但除此之外,所有的行爲都保持不變。

23

我使用這條微模式實現可空系列化:

[XmlIgnore] 
public double? SomeValue { get; set; } 

[XmlAttribute("SomeValue")] // or [XmlElement("SomeValue")] 
[EditorBrowsable(EditorBrowsableState.Never)] 
public double XmlSomeValue { get { return SomeValue.Value; } set { SomeValue= value; } } 
[EditorBrowsable(EditorBrowsableState.Never)] 
public bool XmlSomeValueSpecified { get { return SomeValue.HasValue; } } 

這提供了合適的接口,以毫不妥協的用戶,並仍然沒有序列化時正確的事情。

1

非常有用的發佈幫助了很多。

我選擇使用Scott的修訂Nullable(Of T)數據類型,但是發佈的代碼仍然序列化Nullable元素時它是Null - 儘管沒有「xs:nil ='true'」屬性。

我需要強制串行砸在結構上的標籤完全讓我簡單地實現IXmlSerializable的(這是在VB,但你得到的圖片):

'---------------------------------------------------------------------------- 
    ' GetSchema 
    '---------------------------------------------------------------------------- 
    Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema 
    Return Nothing 
    End Function 

    '---------------------------------------------------------------------------- 
    ' ReadXml 
    '---------------------------------------------------------------------------- 
    Public Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements System.Xml.Serialization.IXmlSerializable.ReadXml 
    If (Not reader.IsEmptyElement) Then 
     If (reader.Read AndAlso reader.NodeType = System.Xml.XmlNodeType.Text) Then 
     Me._value = reader.ReadContentAs(GetType(T), Nothing) 
     End If 
    End If 
    End Sub 

    '---------------------------------------------------------------------------- 
    ' WriteXml 
    '---------------------------------------------------------------------------- 
    Public Sub WriteXml(ByVal writer As System.Xml.XmlWriter) Implements System.Xml.Serialization.IXmlSerializable.WriteXml 
    If (_hasValue) Then 
     writer.WriteValue(Me.Value) 
    End If 
    End Sub 

我喜歡這種方法使用( foo)指定模式,因爲這需要向我的對象添加冗餘屬性的桶負載,而使用新的Nullable類型只需要重新鍵入屬性。

相關問題