2009-07-02 11 views
84

मुझे बस कुछ पागल महसूस हुआ, जिसे मैंने पूरी तरह से असंभव माना: जब किसी ऑब्जेक्ट को deserializing, DataContractSerializer कन्स्ट्रक्टर पर कॉल नहीं करता है!DataContractSerializer मेरे कन्स्ट्रक्टर को कॉल नहीं करता है?

उदाहरण के लिए, इस वर्ग लें:

[DataContract] 
public class Book 
{ 
    public Book() 
    { // breakpoint here 
    } 

    [DataMember(Order = 0)] 
    public string Title { get; set; } 
    [DataMember(Order = 1)] 
    public string Author { get; set; } 
    [DataMember(Order = 2)] 
    public string Summary { get; set; } 
} 

जब मैं उस वर्ग की एक वस्तु deserialize, ब्रेकपाइंट मारा नहीं है। मुझे बिल्कुल पता नहीं है कि यह कैसे संभव है, क्योंकि यह इस वस्तु के लिए एकमात्र निर्माता है!

मैं मान लिया है कि शायद एक अतिरिक्त निर्माता DataContract विशेषता की वजह से संकलक द्वारा उत्पन्न की गई, लेकिन मैं इसे प्रतिबिंब के माध्यम से नहीं मिला ...

तो, मैं जानना चाहते हैं कि क्या यह है: कन्स्ट्रक्टर के बिना मेरी कक्षा का एक उदाहरण कैसे बनाया जा सकता है ??

नोट: मुझे पता है कि मैं OnDeserializing विशेषता का उपयोग कर सकता हूं जब deserialization शुरू होता है, यह मेरे प्रश्न का विषय नहीं है।

+3

या "ऑनडिसेरियलाइज्ड", जब ऑब्जेक्ट को लापता फ़ील्ड भरने के लिए deserializing किया जाता है। –

+1

यह प्रश्न मेरे दिमाग को भी पार कर गया: http://stackoverflow.com/questions/178645/how-does-wcf-deserialization-instantiate-objects-without-calling-a-constructor –

उत्तर

118

DataContractSerializer (जैसे BinaryFormatter) किसी भी निर्माता का उपयोग नहीं करता। यह वस्तु को खाली स्मृति के रूप में बनाता है।

उदाहरण के लिए:

Type type = typeof(Customer); 
    object obj = System.Runtime.Serialization. 
     FormatterServices.GetUninitializedObject(type); 

धारणा है कि deserialization प्रक्रिया (या कॉलबैक यदि आवश्यक हो तो) पूरी तरह से यह प्रारंभ हो जाएगा है।

+82

यह बात कर रहा है !! – Cheeso

+0

निर्माता को deserializing जब बिल्कुल नहीं कहा जाना चाहिए। अगर इसे बुलाया गया था, तो 1) कन्स्ट्रक्टर में आपके द्वारा बनाए गए संसाधनों के बारे में कैसे? वे रिसाव करेंगे! 2) आप वस्तु को दो बार, एक बार कन्स्ट्रक्टर में और एक बार deserialized मूल्यों से शुरू कर रहे हैं। – Dudu

+1

@Dodu a: इससे रिसाव बी नहीं होगा: वह (सीटीओ को कॉल करना) यह है कि कितने सीरियलाइज़र काम करते हैं; किसी भी तरह से आम तौर पर तर्क के रूप में ठीक है क्योंकि व्यवहार समझा जाता है और डिजाइनर के अनुसार डिजाइनर –

3

कुछ परिदृश्य हैं जो इस व्यवहार के बिना संभव नहीं होंगे। निम्नलिखित के बारे में सोचें:

1) आपके पास एक ऑब्जेक्ट है जिसमें एक कन्स्ट्रक्टर है जो "प्रारंभिक" स्थिति में नया उदाहरण सेट करता है। फिर उस उदाहरण पर कुछ तरीकों को बुलाया जाता है, जो इसे "संसाधित" स्थिति में लाता है। आप "संसाधित" स्थिति वाले नए ऑब्जेक्ट्स नहीं बनाना चाहते हैं, लेकिन आप अभी भी उदाहरण को serialize/deserialize करना चाहते हैं।

2) आपने एक निजी कन्स्ट्रक्टर और कुछ स्थैतिक गुणों के साथ एक वर्ग बनाया है जो कि कन्स्ट्रक्टर पैरामीटर के छोटे सेट को नियंत्रित करने के लिए बनाया गया है। अब आप अभी भी उन्हें क्रमबद्ध/deserialize कर सकते हैं।

XmlSerializer आपके पास अपेक्षित व्यवहार है। मुझे XmlSerializer के साथ कुछ समस्याएं आई हैं क्योंकि इसे डिफ़ॉल्ट कन्स्ट्रक्टर की आवश्यकता है। इससे संबंधित, कभी-कभी निजी संपत्ति सेटर्स रखने का अर्थ होता है। लेकिन XmlSerializer को serialize/deserialize करने के लिए गुणों पर सार्वजनिक गेटर और सेटटर की भी आवश्यकता है।

मुझे डेटाकंट्रैक्ट सर्राइज़र/बाइनरीफॉर्मेटर व्यवहार के बारे में लगता है जैसे क्रमिकरण के दौरान एक उदाहरण की स्थिति को निलंबित करना और deserialization के दौरान फिर से शुरू करना। दूसरे शब्दों में, उदाहरण "निर्मित" नहीं हैं बल्कि पहले के राज्य में "बहाल" किए गए हैं।

जैसा कि आपने पहले ही उल्लेख किया है, [ऑनडिसेरियलाइजिंग] विशेषता गैर-धारावाहिक डेटा को सिंक में रखना संभव बनाता है।

+0

मैं यह नहीं कहूंगा कि यह "एक उदाहरण की स्थिति को निलंबित कर देता है" क्योंकि मैंने अभी एक समस्या आई है जहां मेरा डेटामेम्बर इनोटिफ़ाईप्रॉपर्टी का उपयोग कर रहा था और जब निर्माता को नहीं कहा जाता है, तो यह नोटिफ़ाईप्रॉपर्टी को ट्रिगर करेगा, इसलिए व्यवहार को निलंबित नहीं किया जाएगा। – ForceMagic

संबंधित मुद्दे