2010-01-15 18 views
34

करने के लिए एक Nullable Serializing मैं एक वर्ग डेटा के सदस्यों के कई Nullable वस्तुओं रहे हैं क्रमानुसार करने कोशिश कर रहा हूँ, यहाँ रनटाइम पर एक उदाहरण एक्सएमएल

[XmlAttribute("AccountExpirationDate")] 
public Nullable<DateTime> AccountExpirationDate 
{ 
    get { return userPrincipal.AccountExpirationDate; } 
    set { userPrincipal.AccountExpirationDate = value; } 
} 

हालांकि है मैं त्रुटि नहीं मिल सकता System.ullullable`1 [System.DateTime] प्रकार के सदस्य 'AccountExpirationDate' को क्रमबद्ध करें। जटिल प्रकार को एन्कोड करने के लिए XmlAttribute/XmlText का उपयोग नहीं किया जा सकता है।

हालांकि मैंने चेक किया और न्यूलबल SerializableAttribute है। मैं क्या गलत कर रहा हूं?

+0

कुल अनुमान, लेकिन क्या आपने डेटटाइम की कोशिश की है? Nullable के बजाय? –

+1

@Terry - वे समान हैं! –

+0

@Terry, मैं डेटटाइम के रूप में नहीं कर सकता क्योंकि शून्य और उपयोगकर्ता प्रिंसिपल नहीं है। खाता एक्सप्लोरेशनडेट; एक शून्य –

उत्तर

28

आप इसे केवल XmlElement के रूप में क्रमबद्ध कर सकते हैं, XmlAttribute के रूप में नहीं, क्योंकि प्रतिनिधित्व एक विशेषता के लिए बहुत जटिल है। यही अपवाद आपको बता रहा है।

+1

आप अपने स्वयं के कार्यान्वयन को Nullable बना सकते हैं और इसके लिए आवश्यक XML क्रमिकरण गुण लागू कर सकते हैं। –

+0

हां, आप सहमत हो सकते थे। लेकिन कंपाइलर ठीक उसी तरह से इलाज नहीं करेगा जैसा कि अंतर्निहित 'नुल्लाबेले ' है, जिसमें विशेष उपचार है ('==' की अंतर्निहित परिभाषा जैसी चीजों की सोच)। तो अनुशंसित नहीं है। –

+0

@ निकलर्सन - यह स्कीमा को सही ढंग से उत्पन्न करने में सक्षम नहीं होगा जबतक कि आप इसके साथ पागल न हों। –

41

तुम सिर्फ यह चाहते हैं काम, तो शायद करने के लिए:

using System; 
using System.ComponentModel; 
using System.Xml.Serialization; 
public class Account 
{ 
    // your main property; TODO: your version 
    [XmlIgnore] 
    public Nullable<DateTime> AccountExpirationDate {get;set;} 

    // this is a shim property that we use to provide the serialization 
    [XmlAttribute("AccountExpirationDate")] 
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
    public DateTime AccountExpirationDateSerialized 
    { 
     get {return AccountExpirationDate.Value;} 
     set {AccountExpirationDate = value;} 
    } 

    // and here we turn serialization of the value on/off per the value 
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
    public bool ShouldSerializeAccountExpirationDateSerialized() 
    { 
     return AccountExpirationDate.HasValue; 
    } 

    // test it... 
    static void Main() 
    { 
     var ser = new XmlSerializer(typeof(Account)); 
     var obj1 = new Account { AccountExpirationDate = DateTime.Today }; 
     ser.Serialize(Console.Out, obj1); 
     Console.WriteLine(); 
     var obj2 = new Account { AccountExpirationDate = null}; 
     ser.Serialize(Console.Out, obj2); 
    } 
} 

यह विशेषता शामिल केवल होगा जब वहाँ एक गैर-शून्य मान है।

+1

क्या एक्सएमएल सीरिएलाइज़र 'mustSerializeXxxxxxx' विधि के लिए जांच करता है, या यह' AccountExpirationDate.Value' द्वारा फेंक दिया गया अपवाद पकड़कर है जो इसे क्रमबद्ध नहीं करता है? यह कैसे काम करता है? –

+3

@ स्कॉट हां, कंधेरियल * फ्रेमवर्क के कई हिस्सों और एकाधिक धारावाहिक पुस्तकालयों द्वारा उपयोग किया जाने वाला एक पैटर्न है –

+0

deserializing के बारे में क्या है? यदि विशेषता एक्सएमएल में सेट नहीं है, तो शून्य संपत्ति को शून्य होना चाहिए। –

14

मैंने इस तरह कई बार उपयोग किया है।

[XmlIgnore] 
public Nullable<DateTime> AccountExpirationDate 
{ 
    get { return userPrincipal.AccountExpirationDate; } 
    set { userPrincipal.AccountExpirationDate = value; } 
} 

/// 
/// <summary>Used for Xml Serialization</summary> 
/// 
[XmlAttribute("AccountExpirationDate")] 
public string AccountExpirationDateString 
{ 
    get 
    { 
     return AccountExpirationDate.HasValue 
      ? AccountExpirationDate.Value.ToString("yyyy/MM/dd HH:mm:ss.fff") 
      : string.Empty; 
    } 
    set 
    { 
     AccountExpirationDate = 
      !string.IsNullOrEmpty(value) 
      ? DateTime.ParseExact(value, "yyyy/MM/dd HH:mm:ss.fff") 
      : null; 
    } 
} 
+1

मुझे लगता है कि यह होना चाहिए: AccountExpirationDate.Value.ToString ("yyyy/MM/dd hH: mm: ss.fff") – Perhentian

+1

अच्छी पकड़। मैंने इसे ठीक कर दिया है। – fre0n

2

एक सीरियलज़ेबल को परिभाषित करें जो आपकी funcionality encapsulates।

यहां और उदाहरण हैं।

[XmlAttribute("AccountExpirationDate")] 
public SerDateTime AccountExpirationDate 
{ 
    get { return _SerDateTime ; } 
    set { _SerDateTime = value; } 
} 


/// <summary> 
/// Serialize DateTime Class (<i>yyyy-mm-dd</i>) 
/// </summary> 
public class SerDateTime : IXmlSerializable { 
    /// <summary> 
    /// Default Constructor when time is not avalaible 
    /// </summary> 
    public SerDateTime() { } 
    /// <summary> 
    /// Default Constructor when time is avalaible 
    /// </summary> 
    /// <param name="pDateTime"></param> 
    public SerDateTime(DateTime pDateTime) { 
     DateTimeValue = pDateTime; 
    } 

    private DateTime? _DateTimeValue; 
    /// <summary> 
    /// Value 
    /// </summary> 
    public DateTime? DateTimeValue { 
     get { return _DateTimeValue; } 
     set { _DateTimeValue = value; } 
    } 

    // Xml Serialization Infrastructure 
    void IXmlSerializable.WriteXml(XmlWriter writer) { 
     if (DateTimeValue == null) { 
      writer.WriteString(String.Empty); 
     } else { 
      writer.WriteString(DateTimeValue.Value.ToString("yyyy-MM-dd")); 
      //writer.WriteString(SerializeObject.SerializeInternal(DateTimeValue.Value)); 
     } 
    } 

    void IXmlSerializable.ReadXml(XmlReader reader) { 
     reader.ReadStartElement(); 
     String ltValue = reader.ReadString(); 
     reader.ReadEndElement(); 
     if (ltValue.Length == 0) { 
      DateTimeValue = null; 
     } else {     
      //Solo se admite yyyyMMdd 
      //DateTimeValue = (DateTime)SerializeObject.Deserialize(typeof(DateTime), ltValue); 
      DateTimeValue = new DateTime(Int32.Parse(ltValue.Substring(0, 4)), 
           Int32.Parse(ltValue.Substring(5, 2)), 
           Int32.Parse(ltValue.Substring(8, 2)));          
     } 
    } 

    XmlSchema IXmlSerializable.GetSchema() { 
     return (null); 
    } 
} 
#endregion 
2

मैं इसी तरह की समस्या में फंस गया था। मेरे पास एक कक्षा में एक डेटाटाइम संपत्ति (XmlAttribute) थी जो डब्ल्यूसीएफ सेवा में उजागर हुई थी। 1) XmlSerializer वर्ग नल प्रकार

[XmlAttribute] 
public DateTime? lastUpdatedDate { get; set; } 
Exception thrown : Cannot serialize member 'XXX' of type System.Nullable`1. 

2 की XmlAttribute serialising नहीं किया गया था) कुछ पोस्ट [XmlAttribute] [XmlElement साथ बदलने के लिए सुझाव देते हैं (:

नीचे मैं क्या सामना करना पड़ा और समाधान है कि मेरे लिए काम किया है IsNullable = सच)]। लेकिन यह विशेषता को एक तत्व के रूप में क्रमबद्ध करेगा जो पूरी तरह से बेकार है। हालांकि यह XmlElements

3) के लिए ठीक काम करता है 3) कुछ लोग आपकी कक्षा में IXmlSerializable इंटरफेस को लागू करने का सुझाव देते हैं, लेकिन यह डब्ल्यूसीएफ उपभोक्ता अनुप्रयोग से डब्ल्यूसीएफ सेवा को कॉल करने की अनुमति नहीं देता है। तो यह भी इस मामले में काम नहीं करता है।

समाधान:

नल के रूप में संपत्ति को चिह्नित न करें, बल्कि एक ShouldSerializeXXX() विधि का उपयोग अपने बाधा डालने के लिए।

[XmlAttribute] 
public DateTime lastUpdatedDate { get; set; } 
public bool ShouldSerializelastUpdatedDate() 
{ 
    return this.lastUpdatedDate != DateTime.MinValue; 
    // This prevents serializing the field when it has value 1/1/0001  12:00:00 AM 
} 
+0

मुझे लगता है कि आपने ** बिल्कुल ** एक ही उत्तर पोस्ट किया है [यहां] (http://stackoverflow.com/a/29936620/1364007), [यहां] (http://stackoverflow.com/a/29936469/1364007), और [यहां] (http://stackoverflow.com/a/29936390/1364007)। आपकी राय में, क्या सभी तीन प्रश्नों का समाधान बिल्कुल वही है? –

+1

मैं इसका दावा नहीं करता हूं। यदि सटीक नहीं है, कम से कम इसके संदर्भ में। मेरा इरादा उस व्यक्ति को संकेत देना है जो समान मुद्दों का सामना कर रहा है। –