2008-10-28 2 views
81

null 허용 int가있는 클래스가 있습니까? 데이터 유형을 xml 요소로 serialize하도록 설정합니다. 값을 null로 설정하면 xml serializer가 요소를 serialize하지 않도록 설정하는 방법이 있습니까?nullable int를 serialize

[System.Xml.Serialization.XmlElement (IsNullable = false)] 특성을 추가하려고 시도했지만 "IsNullable이 아닐 수 있으므로 형식을 반영하는 오류가 있음을 나타내는 런타임 직렬화 예외가 발생합니다 'false'로 Nullable 형식을 설정하십시오. 'System.Int32'형식을 사용하거나 XmlElement 특성에서 IsNullable 속성을 제거하는 것이 좋습니다. "

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

하지만 주로 내가 MSSQL에서 OPENXML을 사용하는 경우 때문에, 전혀 ID 요소를 원하지 않는 null이 ID에 대한

는, 그것은을 반환

[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; 
     } 
    } 
    ... 
} 

위의 클래스에 직렬화합니다 모양이 null 인 요소에 대해서는 null 대신 0이됩니다.

답변

139

하는 XmlSerializer는 ShouldSerialize{Foo}() 패턴을 지원합니다.

+8

XmlSerializer는 [Foo} Specified 패턴도 지원합니다. –

+23

관련 페이지가 여기에 있습니다 : http://msdn.microsoft.com/en-us/library/53b8022e%28VS.71%29.aspx – cbp

+1

어떤 방법으로 자동 생성 속성이있는 ShouldSerialize를 사용할 수 있습니까? 즉 지역 변수가 없습니다. – Jay

1

불행히도 XmlElementAttribute.IsNullable에 대한 문서에서 설명하는 동작은 그대로 문서화됩니다.

12

두 가지 속성을 사용하여 해결 방법을 알아 냈습니다. int? XmlIgnore 특성 및 serialize 된 개체 속성이있는 속성. 확실하지 XmlSerializer를 한 것을 지원하는 경우 - 또한 {Foo}Specified 패턴이

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

: 당신이 방법을 추가 할 수 있도록

/// <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이 int의 NULL 즉, Flex를 인식하지 못하는 클라이언트의 "자리 표시 자"값으로 인코딩되도록 허용하므로 유용합니다. –

6

와우 덕분에이 질문/답변이 정말 도움이되었습니다. 나는 마음 Stackoverflow.

나는 위에서 조금 더 일반적인 것을 만들었습니다. 우리가 정말로 찾고있는 것은 Nullable에 약간 다른 serialization 동작을 사용하는 것입니다. Reflector를 사용하여 자체 Nullable을 구축했으며 XML serialization이 원하는 방식으로 작동하도록 여기 저기에 몇 가지를 추가했습니다. 꽤 잘 작동하는 것 같습니다.

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로 사용할 수 없게 되나요? 등등 (Nullable <int> 대신 사용해야하지만) 이외의 모든 동작은 동일하게 유지됩니다.

+1

이것은'XmlSerializer.Serialize'에'System.ExecutionEngineException'을 던졌습니다. – modiX

23

나는 Null 허용 직렬화를 구현하기 위해 마이크로 패턴을 사용하고 있습니다 :

[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

SomeValue가 null 일 가능성이 있기 때문에 ... public double XmlSomeValue {get {Return SomeValue.HasValue? SomeValue.Value : 0; } set {SomeValue = value; }} –

+0

XmlSomeValue는 XmlSerializer가 XmlSomeValueSpecified가 참일 때만 만지게됩니다 (즉, SomeValue.Value가 null이 아님). –

+5

총체적이지만 트릭을 수행했습니다. +1 – pettys

1

매우 유용한 게시물은 많은 도움이되었습니다.

Nullable (Of T) 데이터 유형으로 Scott의 개정판을 사용하기로 결정했지만 "xs : nil = 'true'"속성이 없어도 게시 된 코드는 Null 일 때 Nullable 요소를 계속 serialize합니다.(

'---------------------------------------------------------------------------- 
    ' 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 

나는이 방법을 선호를 사용하여 :

나는 (이 VB에 있지만 당신은 사진을 찍어) 구조에 완전히 그래서 단순히 IXmlSerializable 구현 된 태그를 떨어 시리얼 라이저를 강제로 필요 foo) 중복 된 속성의 버킷로드를 내 개체에 추가해야하는 지정된 패턴으로 새로운 Nullable 형식을 사용하면 속성을 다시 타이핑하면됩니다.