2009-04-29 16 views
71

मैं XML पर किसी ऑब्जेक्ट को क्रमबद्ध करने की कोशिश कर रहा हूं जिसमें कई गुण हैं, जिनमें से कुछ केवल पढ़ने योग्य हैं।निजी सदस्य डेटा को क्रमबद्ध करना

public Guid Id { get; private set; } 

मैं कक्षा [Serializable] में चिह्नित किया है और मैं ISerializable इंटरफ़ेस को लागू किया है।

नीचे वह कोड है जिसका उपयोग मैं अपने ऑब्जेक्ट को क्रमबद्ध करने के लिए कर रहा हूं।

public void SaveMyObject(MyObject obj) 
{ 
    XmlSerializer serializer = new XmlSerializer(typeof(MyObject)); 
    TextWriter tw = new StreamWriter(_location); 
    serializer.Serialize(tw, obj); 
    tw.Close(); 
} 

दुर्भाग्य से यह इस संदेश के साथ पहली पंक्ति पर पड़ता है।

अवैधऑपरेशन अपवाद को अनचाहे किया गया था: अस्थायी कक्षा (परिणाम = 1) उत्पन्न करने में असमर्थ। त्रुटि CS0200: संपत्ति या इंडेक्सर 'MyObject.Id' को सौंपा नहीं जा सकता है - यह केवल

पढ़ रहा है, तो मैं जनता के लिए आईडी गुण सेट यह ठीक काम करता है। क्या कोई मुझे बता सकता है कि मैं कुछ कर रहा हूं, या कम से कम यदि यह भी संभव है?

उत्तर

57

आप DataContractSerializer इस्तेमाल कर सकते हैं (लेकिन ध्यान दें कि आप जिम्मेदार बताते हैं एक्सएमएल का उपयोग नहीं कर सकते हैं - केवल एक्सएमएल तत्व):

using System; 
using System.Runtime.Serialization; 
using System.Xml; 
[DataContract] 
class MyObject { 
    public MyObject(Guid id) { this.id = id; } 
    [DataMember(Name="Id")] 
    private Guid id; 
    public Guid Id { get {return id;}} 
} 
static class Program { 
    static void Main() { 
     var ser = new DataContractSerializer(typeof(MyObject)); 
     var obj = new MyObject(Guid.NewGuid()); 
     using(XmlWriter xw = XmlWriter.Create(Console.Out)) { 
      ser.WriteObject(xw, obj); 
     } 
    } 
} 

वैकल्पिक रूप से, आप IXmlSerializable को लागू करने और सब कुछ अपने आप कर सकते हैं - लेकिन इस XmlSerializer साथ काम करता है कम से कम, ।

+0

+1, मेरे उत्तर पर सलाह के लिए धन्यवाद। –

+0

मैंने अपने कोड को DataContractSerializer का उपयोग करने के लिए बदल दिया है और मैंने देखा है कि यह अभी भी GetObjectData विधि चला रहा है। क्या मैं यह सोचने में सही हूं कि मैं या तो मेरे गुणों पर गुणों को क्रमबद्ध करने के लिए गुण डाल सकता हूं, या मैं आईएसरियलज़ेबल इंटरफ़ेस को कार्यान्वित कर सकता हूं? –

+0

यदि आप ISerializable लागू करते हैं (या यह IXmlSeializable है?), तो आप मूल रूप से सभी काम कर रहे हैं ... –

6

आप System.Runtime.Serialization.NetDataContractSerializer का उपयोग कर सकते हैं। यह अधिक शक्तिशाली है और क्लासिक एक्सएमएल सीरिएलाइज़र के कुछ मुद्दों को हल करता है।

ध्यान दें कि इस के लिए अलग-अलग विशेषताएं हैं।

[DataContract] 
public class X 
{ 
    [DataMember] 
    public Guid Id { get; private set; } 
} 


NetDataContractSerializer serializer = new NetDataContractSerializer(); 
TextWriter tw = new StreamWriter(_location); 
serializer.Serialize(tw, obj); 

संपादित करें:

अद्यतन मार्क की टिप्पणी के आधार पर: आप शायद अपने मामले के लिए System.Runtime.Serialization.DataContractSerializer का उपयोग करना चाहिए एक साफ एक्सएमएल मिलता है। शेष कोड वही है।

+0

नेटडाटाकंट्रैक्टसेरियलाइज़र xml नहीं लिखता है ... - या इसके बजाय, यह बाहरी खपत के लिए उपयुक्त xml उपयुक्त नहीं है - इसमें असेंबली मेटाडेटा है। –

+0

@Marc: संकेत के लिए धन्यवाद। यह हमेशा इस बात पर निर्भर करता है कि कोई क्या हासिल करना चाहता है। DataContractSerializer शायद यहां अपेक्षित है। –

1

पढ़ें केवल क्षेत्रों, इस readonly कीवर्ड

MSDN से की प्रकृति के कारण है XmlSerializer का उपयोग कर धारावाहिक नहीं किया जाएगा:

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

तो ... आप काफी है कि विशेष रूप क्रमबद्धता मोड के साथ डिफ़ॉल्ट निर्माता में खेतों मूल्य ...

+0

मैंने सोचा था कि क्योंकि मैंने ISerializable.GetObjectData विधि को लागू किया था, XmlSerializer उस जानकारी को प्राप्त करने के लिए उपयोग करेगा जिसे मैं धारावाहिक बनाना चाहता था, और मेरी पढ़ाई केवल गुणों को आजमाएं और एक्सेस न करें । –

+0

XmlSerializer को आईएसरियलज़ेबल के बारे में परवाह नहीं है - केवल IXmlSerializable –

+0

मार्क धन्यवाद, यह समझ में आता है। –

0

इसकी संभव नहीं सेट (समाधान के लिए अन्य टिप्पणी देखें) की आवश्यकता होगी। यदि आप वास्तव में अपने क्रमिकरण मोड को छोड़ना चाहते हैं, तो आपको इस पर ढांचे की सीमाओं के आसपास काम करना होगा।यह example

अनिवार्य रूप से, public संपत्ति को चिह्नित करें, लेकिन अगर इसे किसी भी समय deserialization के अलावा उपयोग किया जाता है तो अपवाद फेंक दें।

+5

"लेकिन एक अपवाद फेंक दें" - चूंकि XmlSerializer serialization कॉलबैक का समर्थन नहीं करता है, इसलिए आपके पास जानने का कोई तरीका नहीं है ... –

+1

आप अपनी संपत्ति को कॉल करने के बारे में जानने के लिए 'System.Diagnostics.StackTrace' का उपयोग कर सकते हैं, लेकिन मैं नहीं ऐसे समाधान की सिफारिश करें :-) –

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