2012-02-17 34 views
11

के बाद निजी रीडोनली फ़ील्ड प्रारंभ करें मुझे Deserialization के बाद निजी रीडोनली फ़ील्ड को प्रारंभ करने की आवश्यकता है। मैं DataContract folowing हैDeserializing

[DataContract] 
public class Item 
{ 
    public Item() 
    { 
     // Constructor not called at Deserialization 
     // because of FormatterServices.GetUninitializedObject is used 
     // so field will not be initialized by constructor at Deserialization 
     _privateReadonlyField = new object(); 
    } 

    // Initialization will not be called at Deserialization (same reason as for constructor) 
    private readonly object _privateReadonlyField = new object(); 

    [DataMember] 
    public string SomeSerializableProperty { get; set; } 

    [OnDeserializing] 
    public void OnDeserializing(StreamingContext context) 
    { 
     // With this line code even not compiles, since readonly fields can be initialized only in constructor 
     _privateReadonlyField = new object(); 
    } 
} 

सभी मैं क्या जरूरत है, उसके बाद Deserialization _privateReadonlyField अशक्त नहीं है।

इस बारे में कोई सुझाव - क्या यह संभव है? या मुझे "केवल पढ़ने योग्य" कुंजी को हटाने की आवश्यकता है, जो एक अच्छा विकल्प नहीं है।

+0

आप क्या क्रमांकन विधि का उपयोग कर रहे हैं? वस्तुओं का निर्माण विभिन्न तरीकों के लिए अलग है। –

+0

आपके '_privateReadonlyField' को' [DataMember] 'चिह्नित करने में क्या गड़बड़ है? डेटा अनुबंध serializer बिना किसी समस्या के इसका ख्याल रखेगा। – dasblinkenlight

+0

जोआचिम इसाक्सन: मैं डेटाकंट्रैक्टजसनसेरियलाइज़र का उपयोग कर रहा हूं लेकिन असल में इससे कोई फर्क नहीं पड़ता - सभी सीरियलाइज़र Deserializing जब FormatterServices.GetUninitializedObject का उपयोग करते हैं। – Andris

उत्तर

7

private readonly के रूप में घोषित कोई भी क्षेत्र उसी पंक्ति में तत्काल किया जा सकता है जहां इसे घोषित किया गया था या एक निर्माता के अंदर। एक बार ऐसा करने के बाद इसे बदला नहीं जा सकता है।

MSDN से:

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

इसका मतलब है कि आपको इसे काम करने के लिए readonly कीवर्ड को हटाना होगा।

+0

धन्यवाद, हुसके। दुर्भाग्य से आपने इस बारे में मेरी भावना को मंजूरी दे दी, मुझे उम्मीद थी कि इस समस्या को हल करने के लिए कुछ रास्ता मौजूद है। प्रतिक्रिया के लिए – Andris

8

सीरियलाइजेशन केवल पढ़ने के लिए फ़ील्ड के मानों में पढ़ने में सक्षम है क्योंकि यह प्रतिबिंब का उपयोग करता है, जो अभिगम्यता नियमों को अनदेखा करता है। यह तर्क दिया जा सकता है कि निम्नलिखित क्रमबद्धता की प्रक्रिया के हिस्से के रूप में, इसलिए उचित है, भले ही मैं लगभग किसी भी अन्य परिस्थिति में इसके खिलाफ दृढ़ता से अनुशंसा करते हैं:

private readonly Doodad _oldField; 

[OptionalField(VersionAdded = 2)] 
private readonly Widget _newField; 

[OnDeserialized] 
private void OnDeserialized(StreamingContext context) 
{ 
    if (_oldField != null && _newField == null) 
    { 
     var field = GetType().GetField("_newField", 
      System.Reflection.BindingFlags.Instance | 
      System.Reflection.BindingFlags.DeclaredOnly | 
      System.Reflection.BindingFlags.NonPublic); 
     field.SetValue(this, new Widget(_oldField)); 
    } 
} 
+1

धन्यवाद। प्रश्न पूछने पर मैं वास्तव में प्रतिबिंब के बारे में भूल गया। – Andris

+0

इस समाधान पर '[OptionalField] 'विशेषता का क्या प्रभाव है? क्या 'ऑनडिसेरियलाइज्ड' अभी भी इसके बिना काम करता है? –

+0

यदि मुझे सही तरीके से याद है, तो इसे छोड़कर उस क्षेत्र को शामिल करते समय इनपुट को पढ़ने पर अपवाद फेंकने का कारण बन जाएगा। –

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