2010-03-30 8 views
9

यहाँ मेरी कक्षा है:सी # में शून्य करने के लिए शून्य सरणी को deserialize कैसे करें?

public class Command 
{ 
    [XmlArray(IsNullable = true)] 
    public List<Parameter> To { get; set; } 
} 

जब मैं इस वर्ग की एक वस्तु को क्रमानुसार:

var s = new XmlSerializer(typeof(Command)); 
s.Serialize(Console.Out, new Command()); 

यह के रूप में प्रिंट की उम्मीद (xml शीर्ष और डिफ़ॉल्ट एमएस नामस्थान छोड़े गए हैं):

<Command><To xsi:nil="true" /></Command> 

जब मैंने यह एक्सएमएल लिया और इसे deserialize करने की कोशिश की मैं अटक गया, क्योंकि यह हमेशा "शून्य नहीं" प्रिंट:

var t = s.Deserialize(...); 
if (t.To == null) 
    Console.WriteLine("Null"); 
else 
    Console.WriteLine("Not null"); 

मेरी सूची को शून्य बनाने के लिए deserializer को कैसे बल दें, अगर यह xml में शून्य है?

+0

यह वास्तव में है कि आप के लिए महत्वपूर्ण है के रूप में यदि आप कोई सूची या एक खाली सूची है का उपयोग करते हैं? –

+0

हाँ। मैं निश्चित रूप से कुछ झंडे के साथ इस मामले को हल कर सकता हूं, लेकिन मैं जानना चाहता हूं कि कोई अच्छा मानक समाधान है या नहीं। –

+1

नल ऑब्जेक्ट्स से बचना आम तौर पर एक अच्छी बात है (कम त्रुटि-प्रवण, कोड के चारों ओर नल की जांच करने की आवश्यकता नहीं है)। ध्वज का उपयोग स्पष्ट रूप से इंगित करेगा कि वास्तव में उस शून्य मान का प्रतिनिधित्व करता है। – Groo

उत्तर

2

ओह, कष्टप्रद नहीं है यह। आप इसे अपने असेंबली पर/रखना और/डीबग विकल्पों के साथ sgen.exe चलाकर कर रहे हैं ताकि आप deserialization कोड डीबग कर सकें। यह लगभग इस तरह दिखता है:

global::Command o; 
o = new global::Command(); 
if ((object)([email protected]) == null) [email protected] = new global::System.Collections.Generic.List<global::Parameter>(); 
global::System.Collections.Generic.List<global::Parameter> a_0 = (global::System.Collections.Generic.List<global::Parameter>)[email protected]; 
// code elided 
//... 
while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && Reader.NodeType != System.Xml.XmlNodeType.None) { 
    if (Reader.NodeType == System.Xml.XmlNodeType.Element) { 
    if (((object)Reader.LocalName == (object)id4_To && (object)Reader.NamespaceURI == (object)id2_Item)) { 
     if (!ReadNull()) { 
     if ((object)([email protected]) == null) [email protected] = new global::System.Collections.Generic.List<global::Parameter>(); 
     global::System.Collections.Generic.List<global::Parameter> a_0_0 = (global::System.Collections.Generic.List<global::Parameter>)[email protected]; 
     // code elided 
     //... 
     } 
     else { 
     // Problem here: 
     if ((object)([email protected]) == null) [email protected] = new global::System.Collections.Generic.List<global::Parameter>(); 
     global::System.Collections.Generic.List<global::Parameter> a_0_0 = (global::System.Collections.Generic.List<global::Parameter>)[email protected]; 
     } 
    } 
    } 
    Reader.MoveToContent(); 
    CheckReaderCount(ref whileIterations1, ref readerCount1); 
} 
ReadEndElement(); 
return o; 

3 से कम स्थानों पर जहां यह सुनिश्चित करता है कि @To संपत्ति शून्य नहीं है। पहली बात कुछ हद तक रक्षात्मक है, जब संरचना मौजूद नहीं है तो डेटा को deserialize करना मुश्किल है। दूसरा एक शून्य परीक्षण फिर से करता है, यह एकमात्र असली अच्छा है। तीसरा एक समस्या है, ReadNull() सच हो गया है लेकिन यह अभी भी एक गैर-शून्य संपत्ति मान बनाता है।

यदि आप खाली और शून्य के बीच अंतर करना चाहते हैं तो आपके पास कोई अच्छा समाधान नहीं है लेकिन इस कोड को हाथ से संपादित करें। यदि आप वास्तव में हताश हैं और कक्षा 100% स्थिर है तो यह केवल करें। अच्छा, ऐसा मत करो। जोआओ का समाधान एकमात्र अच्छा है।

+0

धन्यवाद। मैं झंडे जोड़ दूंगा। –

0

मैं @ ओलिवर की टिप्पणी से सहमत हूं, लेकिन अगर आप इसे पूरी तरह से वापस करने की आवश्यकता है तो आप इसे इस तरह हल कर सकते हैं। स्वचालित संपत्ति का उपयोग करने के बजाय, अपना स्वयं का बैकिंग फ़ील्ड बनाएं।

List<Parameter> _to; 
public List<Parameter> To 
{ 
    get 
    { 
     if (_to != null && _to.Count == 0) return null; 
     return _to; 
    } 
    set { _to = value; } 
} 
+0

मेरा मानना ​​है कि ओपी * शून्य और खाली सूचियों को अलग करना चाहता था। – Groo

+0

दुर्भाग्य से, मेरे मामले में, खाली सूची और शून्य सूची अलग हैं। –

+0

यह इसे और अधिक जटिल बनाता है :( –

0

तुम सच में की जरूरत है कि एक संग्रह null को deserialized है जब कोई मान दिए जाते हैं आप, एक set एक्सेसर प्रदान नहीं इस तरह से यह कर सकते हैं, तो:

public class Command 
{ 
    private List<Parameter> to; 

    public List<Parameter> To { get { return this.to; } } 
} 
+0

खराब विकल्प। "करने के लिए" deserialization के बाद हमेशा शून्य होगा। –

3

आप एक सरणी के बजाय एक सूची यह काम करता है उम्मीद

public class Command 
{ 
    [XmlArray(IsNullable = true)] 
    public Parameter[] To { get; set; } 
} 
संबंधित मुद्दे