एक अशक्त int को सीरियलाइज़ करें


92

मेरे पास एक अशक्त इंट के साथ एक वर्ग है? एक xml तत्व के रूप में अनुक्रमित करने के लिए डेटाटाइप सेट। क्या इसे स्थापित करने का कोई तरीका है ताकि xml धारावाहिक तत्व तत्व को क्रमांकित नहीं करेगा यदि मान शून्य है?

मैंने [System.Xml.Serialization.XmlElement (IsNullable = false)] विशेषता को जोड़ने का प्रयास किया है, लेकिन मुझे रनटाइम क्रमांकन अपवाद मिलता है जिसमें कहा गया था कि टाइप को दर्शाती एक त्रुटि थी, क्योंकि "IsNullable को 'असत्य पर सेट नहीं किया जा सकता है। एक अशक्त प्रकार के लिए। 'System.Int32' प्रकार का उपयोग करने पर विचार करें या XNEE विशेषता से IsNullable गुण को हटा दें। "

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

लेकिन उन आईडी के लिए जो अशक्त हैं, मैं मुख्य रूप से आईडी तत्व नहीं चाहता, क्योंकि जब मैं MSSQL में OPENXML का उपयोग करता हूं, तो यह उस तत्व के लिए शून्य के बजाय 0 देता है जो दिखता है

जवाबों:


149

XmlSerializer ShouldSerialize{Foo}()पैटर्न का समर्थन करता है , इसलिए आप एक विधि जोड़ सकते हैं:

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

{Foo}Specifiedपैटर्न भी है - सुनिश्चित नहीं है कि XmlSerializer उस का समर्थन करता है।


8
XmlSerializer भी [Foo} निर्दिष्ट पैटर्न का समर्थन करता है।
डेविड श्मिट

23
रीलेवेंट पेज यहाँ है: msdn.microsoft.com/en-us/library/53b8022e%28VS.71%29.aspx
cbp

1
ऑटो-जनरेटेड प्रॉपर्टीज़ के साथ कंधों का उपयोग करने का कोई तरीका <प्रोप>? यानी कोई स्थानीय चर।
Jay

1
@ जय: किसी की जरूरत नहीं। आप बस HasValueसंपत्ति पर कॉल कर सकते हैं।
स्टीवन सुदित

1
@मार्क यदि, सदस्य (संपत्ति / क्षेत्र) के लिए Fooभी आपके पास है public bool FooSpecified {get {...} set {...}}, तो getइसका उपयोग यह देखने के लिए किया जाता है कि Fooक्या इसे क्रमबद्ध किया जाना चाहिए, और setयह कहा जाता है Fooकि डीसर्बलाइजेशन के दौरान एक मान निर्दिष्ट करते समय ।
मार्क Gravell

26

मैं इस सूक्ष्म पैटर्न का उपयोग अशक्त क्रमांकन को लागू करने के लिए कर रहा हूं:

[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 शून्य हो सकता है ... सार्वजनिक डबल XmlSomeValue {get {वापसी SomeValue.HasValue? SomeValue.Value: 0; } सेट {SomeValue = मूल्य; }}
डग डॉमनी

XmlSomeValue केवल XmlSerializer द्वारा उपयोग किया जाने वाला माना जाता है जो केवल तभी इसे स्पर्श करेगा जब XmlSomeValueSpecified सत्य है (अर्थात SomeValue.Value शून्य नहीं है।
डेविड

@पट्टी: यह एक्सएमएल है, आप क्या उम्मीद करते हैं? ;-)
डेविड श्मिट

स्वीकृत उत्तर 2008 से है। यह अभी एक होना चाहिए। निर्दिष्ट बनाम कंधे से संबंधित दिलचस्प जवाब
daniloquio

निश्चित रूप से शीर्ष उत्तर होना चाहिए।
tyteen4a03 15

12

मुझे दो गुणों का उपयोग करते हुए वर्कअराउंड का पता चला। एक इंट? एक 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());
            }
        }
    }

यह समाधान बहुत अच्छा है क्योंकि यह NULL को क्लाइंट्स के लिए "प्लेसहोल्डर" मान के रूप में एन्कोडेड करने की अनुमति देता है, जो NULLs को ints, यानी Flex में नहीं पहचानता है।
कुबा व्यारोसेक

आप [EditorBrowsable (EditorBrowsableState.Never)] को एक्सएमएल क्रमांकित संपत्ति में एविओड में जोड़कर देख सकते हैं जब कोडिंग
एंटोनियो रोड्रिगेज

6

वाह धन्यवाद इस सवाल / जवाब ने वास्तव में मेरी मदद की। मैं स्टैकओवरफ़्लो को दिल से मानता हूँ।

मैंने वह बनाया जो आप थोड़ा और सामान्य से ऊपर कर रहे हैं। हम वास्तव में देख रहे हैं कि थोड़ा अलग क्रमांकन व्यवहार के साथ अशक्त है। मैंने अपने स्वयं के Nullable का निर्माण करने के लिए Reflector का उपयोग किया, और 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;
}

आप अपने सदस्यों को इंट करने की क्षमता खो देते हैं? और इतने पर (इसके बजाय Nullable <int> का उपयोग करना है) लेकिन इसके अलावा सभी व्यवहार समान हैं।


1
यह मुझ System.ExecutionEngineExceptionपर एक फेंकता है XmlSerializer.Serialize
मार्टिन ब्रौन

1

दुर्भाग्य से, आपके द्वारा वर्णित व्यवहार XmlElementAttribute.IsNullable के लिए डॉक्स में सटीक रूप से प्रलेखित हैं।


1

बहुत उपयोगी पोस्टिंग ने बहुत हद तक मदद की।

मैंने Nullable (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 प्रकार का उपयोग करने के लिए केवल गुणों के पुन: उपयोग की आवश्यकता होती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.