2009-04-23 10 views
8

का संस्करण बनाया गया है, मैं बाइनरीफॉर्मेटर (सी #) के साथ एक वृक्षदृश्य को क्रमबद्ध करता था। विधानसभा जिसने केवल यही किया है और जिसमें सभी धारावाहिक वर्ग शामिल हैं, अब एक मजबूत नाम है और हस्ताक्षरित है और एक नया संस्करण संख्या भी मिली है (हालांकि, कार्यान्वयन नहीं बदला गया)।असेंबली में ऑब्जेक्ट को डिसेरियलाइज़ करें जिसे अब हस्ताक्षर किया गया है और

जब मैं बाइट [] सरणी deserialize करने की कोशिश, लाइन

(TreeViewData)binaryFormatter.Deserialize(memoryStream); 

एक ArgumentNullException पैदा करता है। (पैरामीटर नाम: प्रकार)

मैंने सोचा कि संस्करण संख्या समस्या है, इसलिए मैंने एक स्वयं बाइंडर लागू किया। मैं BindToType विधि को ओवरराइट करता हूं और यह सुनिश्चित करता हूं कि संस्करण सही किया गया है और सही प्रकार लौटाया गया है।

हालांकि, फिलहाल, कार्यक्रम BindToType विधि को छोड़ देता है, मुझे अभी भी ऊपर उल्लिखित अपवाद मिलता है।

मैं इसे कैसे ठीक करूं?

उत्तर

3

आप को एक क्रमबद्ध सरोगेट का उपयोग करके आजमा सकते हैं, लेकिन बिना किसी चीज के हम इसे पुन: पेश कर सकते हैं, यह एक सभ्य उत्तर देना मुश्किल होगा।

मूलभूत समस्या यह है कि बाइनरीफॉर्मेटर असेंबली जैसी चीजों की बात करते समय बहुत ही भंगुर है। बिल्ली, यह within an assembly भी भंगुर है।

ऐसा लगता है जैसे TreeViewData पेड़ आधारित है, इसलिए मुझे आश्चर्य है कि क्या एक्सएमएल बेहतर होगा (यानी अधिक संस्करण सहिष्णु) विकल्प। यदि दक्षता चिंता का विषय है, तो कस्टम बाइनरी प्रारूप (जैसे protobuf-net) हैं जो उच्च प्रदर्शन, संस्करण सहिष्णु, पोर्टेबल बाइनरी क्रमबद्धता प्रदान करते हैं। यदि आपका डेटा पहले से ही क्रमबद्ध है ... मुझे आश्चर्य है कि क्या यह ट्रैक बदलने का समय हो सकता है? डेटा को deserialize करने के लिए पुरानी असेंबली का उपयोग करने का प्रयास करें, और एक और मजबूत serialization रणनीति पर स्विच करें।

11

आप इस को हल करने के लिए एक SerializationBinder उपयोग कर सकते हैं:

private class WeakToStrongNameUpgradeBinder : SerializationBinder 
{ 
    public override Type BindToType(string assemblyName, string typeName) 
    { 
     try 
     { 
      //Get the name of the assembly, ignoring versions and public keys. 
      string shortAssemblyName = assemblyName.Split(',')[0]; 
      var assembly = Assembly.Load(shortAssemblyName); 
      var type = assembly.GetType(typeName); 
      return type; 
     } 
     catch (Exception) 
     { 
      //Revert to default binding behaviour. 
      return null; 
     } 
    } 
} 

फिर

var formatter = new BinaryFormatter(); 
formatter.Binder = new WeakToStrongNameUpgradeBinder(); 

देखा, अपने पुराने धारावाहिक वस्तुओं इस फ़ॉर्मेटर साथ deserialized जा सकता है। यदि प्रकार भी बदल गया है तो आप पुराने प्रकारों को अपने नए प्रकारों में deserialize करने के लिए SerializationSurrogate का उपयोग कर सकते हैं।

जैसा कि अन्य ने उल्लेख किया है, IFormatter पर निर्भर होने के बजाय अपना स्वयं का क्रमिकरण करना एक अच्छा विचार है क्योंकि आपके पास संस्करण और क्रमबद्ध आकार पर अधिक नियंत्रण है।

+0

ओह बहुत बहुत धन्यवाद। –

1

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