6

मैं एक एक पुराने अनुप्रयोग है कि BinaryFormatter इस्तेमाल किया filestream में आवेदन डेटा को क्रमानुसार करने काम करना है किसी भी optimizazion बिना ("data.oldformat" नामक फ़ाइल में कहते हैं) मुख्य वर्ग विशेषताISerializable और पश्चगामी संगतता

के साथ चिह्नित किया गया है
<serializable()>public MainClass 
....... 
end class 

और क्रमबद्धता कोड

dim b as new binaryformatter 
b.serialize(mystream,mymainclass) 

क्रमबद्धता/deserialization प्रक्रिया मैं बस वर्ग ISerializable इंटरफ़ेस को लागू किया जाता का अनुकूलन करने की कोशिश में है और कुछ अनुकूलित seriali लिखा था zation दिनचर्या

<serializable()>public MainClass 
     implements ISerializable 
....... 
end class 

अनुकूलन वास्तव में अच्छी तरह से काम करता है, लेकिन मैं पिछली संगतता के लिए पुरानी फ़ाइलों के अंदर डेटा reatrive करने के लिए एक रास्ता खोजने चाहिए।

मैं यह कैसे कर सकता हूं ??

Pierluigi

उत्तर

4

stmax लेकिन मैं इसे इस, जो SerializationEntry.GetEnumerator() बजाय try/catch का उपयोग करता है की तरह लागू होता है, एक उत्कृष्ट उत्तर नहीं है। इस तरह से क्लीनर और काफी तेज है।

public MainClass(SerializationInfo info, StreamingContext context) { 
    int version = 0; 
    foreach (SerializationEntry s in info) 
    { 
     if (s.Name == "version") 
     { 
      version = (int)s.Value; 
      break; 
     } 
    } 

    switch (version) { 
     case 0: 
     // deserialize "old format" 
     break; 
     case 1: 
     // deserialize "new format, version 1" 
     break; 
     default: 
     throw new NotSupportedException("version " + version + " is not supported."); 
    } 
} 

मैं) .FirstOrDefault (का उपयोग कर एक LINQ संस्करण पसंद करेंगे, लेकिन SerializationInfo IEnumerable लागू नहीं करता है - चेहरे में, अजीब तरह से पर्याप्त है, यह यहां तक ​​कि पुराने IEnumerable इंटरफ़ेस को लागू नहीं करता है।

0

बस एक ही बात की कोशिश आप अब तक कर रहा हूँ

BinaryFormatter b = new BinaryFormatter(); 
MainClass a = b.DeSerialize(mystream) as MainClass; 

कार्यान्वयन ISerializable अपने मूल वर्ग परिवर्तन नहीं किया, मूल रूप से आप सिर्फ कुछ तरीकों

+0

मैंने आवश्यक कन्स्ट्रक्टर (serializationInfo जानकारी, स्ट्रीमिंग कॉन्टेक्स्ट संदर्भ) जोड़ा है, इसलिए मैं डिफ़ॉल्ट क्रमबद्धता – pierusch

0

जोड़ दिया है जब आपकी ऑब्जेक्ट्स को क्रमबद्ध करना एक अतिरिक्त संस्करण फ़ील्ड जोड़ता है (इसमें बहुत अधिक ओवरहेड नहीं जोड़ना चाहिए)। फिर अपने GetObjectData विधि में, पहले संस्करण फ़ील्ड को पुनर्प्राप्त करने का प्रयास करें और इस पर आधारित है कि यह मौजूद है या नहीं (SerializationException को पकड़कर) पुराने तरीके या नए तरीके को deserialize। पुराने तरीके से सिर्फ सभी डेटा को क्रमबद्ध किया जाएगा ताकि आपको सभी क्षेत्रों के लिए ... कॉल करने में सक्षम होना चाहिए।

+0

के दौरान अपना स्वयं का डेटा सहेजने के बिना b.deserialize का उपयोग नहीं कर सकता, यह क्रमबद्ध प्रक्रिया के लिए ठीक है तो मैं streaminginfo का उपयोग कर डेटा पुनः प्राप्त करने के लिए कैसे पता नहीं है getObjectData लेकिन समस्या अक्रमांकन प्रक्रिया है जो एक विशेष निर्माता नई उपयोग करता है (serializationinfo के रूप में जानकारी, serializationcontext के रूप में संदर्भ) वर्ष mainClass संस्करण ISerializable लागू नहीं होने की है ऑब्जेक्ट – pierusch

0

आपका पिछला कोड काम करना चाहिए। क्या आपको अपवाद मिलता है? नए निर्माता का उपयोग करने का प्रयास करें:

public MainClass(SerializationInfo info, StreamingContext context) {} 

आप जानकारी-वस्तु पारित कर उपयोग कर सकते हैं:

Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext) 
+0

मैं था .. लेकिन यह जानने की आवश्यकता है कि बाइनरीफॉर्मर डेटा को कैसे सहेजता है जब कक्षा को केवल क्रमिक के रूप में चिह्नित किया जाता है ... – pierusch

4

के बाद से आप पहले से ही ISerializable इंटरफ़ेस को क्रियान्वित किया है, तो आप शायद यह भी पहले से ही आवश्यक निर्माता जोड़ दिया है धारावाहिक फ़ाइल से डेटा पुनर्प्राप्त करने के लिए निर्माता को। डिफ़ॉल्ट रूप से (यानी जब कोई ISerializable लागू नहीं किया जाता है), फ़ील्ड नामों को क्रमिकरण के दौरान पहचानकर्ता के रूप में उपयोग किया जाता है। यदि ऐसा है तो अपने पुराने वर्ग एक क्षेत्र था "पूर्णांक एक्स" क्या आप इस का उपयोग कर deserialize कर सकते हैं:

this.x = info.GetInt32("x"); 

नए संस्करणों के लिए मैं आम तौर पर एक "संस्करण" प्रविष्टि क्रमबद्धता के दौरान, इस तरह जोड़ें:

public void GetObjectData(SerializationInfo info, StreamingContext context) { 
    info.AddValue("version", 1); 
    info.AddValue("othervalues", ...); 
} 

अक्रमांकन दौरान आप इस संस्करण प्रविष्टि जांचें और तदनुसार deserialize कर सकते हैं:

public MainClass(SerializationInfo info, StreamingContext context) { 
    int version; 
    try { 
     version = info.GetInt32("version"); 
    } 
    catch { 
     version = 0; 
    } 

    switch (version) { 
     case 0: 
     // deserialize "old format" 
     break; 
     case 1: 
     // deserialize "new format, version 1" 
     break; 
     default: 
     throw new NotSupportedException("version " + version + " is not supported."); 
    } 
} 

मैं उस कोड संकलित नहीं किया है, लिखने की त्रुटियों हो सकता है।

उम्मीद है कि मदद करता है।

+0

महान उत्तर stmax! बाइनरीफॉर्मर ऑब्जेक्ट के लिए आपको डिफ़ॉल्ट व्यवहार कैसे मिला? – pierusch

+3

मैंने उन प्रविष्टियों के "नाम" को खोजने के लिए निम्नलिखित किया जो डिफ़ॉल्ट व्यवहार के साथ क्रमबद्ध थे: foreach (info.GetEnumerator() में SerializationEntry प्रविष्टि {Trace.WriteLine (entry.Name); } – stmax

+0

"संस्करण" प्राप्त करने के दौरान प्रयास/पकड़ने के बजाय, इसके बजाय SerializationInfo.GetEnumerator() का उपयोग करें और "संस्करण" फ़ील्ड के लिए खोजें। यह क्लीनर है और यदि क्षेत्र नहीं मिला है तो अपवाद फेंकने से बचने से पूरे deserialization (मेरे परीक्षण में) 2x तेज बनाता है। SerializationInfo.Get() आंतरिक रूप से एक ही रैखिक खोज का उपयोग करता है क्योंकि यह स्वयं को एक गणक के साथ कर रहा है, जिससे उन्हें फ़ील्ड की संख्या में ओ (एन) दोनों बना दिया जाता है। –

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