7

मैं कुछ ऑब्जेक्ट्स के LazyCollection वाले किसी ऑब्जेक्ट को सीरियललाइज़ और डीसिरियलाइज़ करना चाहता हूं।आलसी ऑब्जेक्ट को deserialize करने में सक्षम नहीं

आम तौर पर सबकुछ ठीक से काम करता है लेकिन, यदि धारावाहिकरण के लिए उपयोग की जाने वाली कक्षाओं के नामस्थान बदल दिए जाते हैं, तो यह समस्या होती है।

मैंने deserializing जबकि सही कक्षाओं को इंगित करने के लिए SerializationBinder लिखा है। लेकिन किसी कारण से, मुझे deserialized मूल्य नहीं मिल रहा है।

निम्नलिखित कोड स्निपेट मुझे जो समस्या मिल रही है उसे बताती है;

क्रमबद्धता के लिए इस्तेमाल किया क्लास:

namespace ConsoleApplication14 
{ 
    [Serializable] 
    public class MyInnerClass : ISerializable 
    { 
     private string _stringInInnerClassKey = "StringInInnerClass"; 
     public string StringInInnerClass { get; set; } 

     public MyInnerClass() { } 

     private MyInnerClass(SerializationInfo info, StreamingContext context) 
     { 
      StringInInnerClass = info.GetString(_stringInInnerClassKey); 
     } 

     public void GetObjectData(SerializationInfo info, StreamingContext context) 
     { 
      info.AddValue(_stringInInnerClassKey, StringInInnerClass); 
     } 
    } 

    [Serializable] 
    public class MyOuterClass : ISerializable 
    { 
     private string _collectionOfObjKey = "CollectionOfInnerObj"; 
     public Lazy<Collection<MyInnerClass>> CollectionOfInnerObj { get; set; } 

     private MyOuterClass(SerializationInfo info, StreamingContext context) 
     { 
      if (info == null) throw new ArgumentNullException("serializationInfo"); 

      CollectionOfInnerObj = 
       (Lazy<Collection<MyInnerClass>>) 
        info.GetValue(_collectionOfObjKey, typeof(Lazy<Collection<MyInnerClass>>)); 
     } 

     public MyOuterClass() { } 

     public void GetObjectData(SerializationInfo info, StreamingContext context) 
     { 
      if (info == null) throw new ArgumentNullException(); 

      info.AddValue(_collectionOfObjKey, CollectionOfInnerObj, typeof(Lazy<Collection<MyInnerClass>>)); 
     } 
    } 
} 

ही वर्गों के ऊपर, Deserialization के लिए उपयोग किया जाता है, लेकिन केवल नाम स्थान काम करने के लिए ConsoleApplication14.OtherNamespace

परिवर्तित करने के लिए इस तरह के Deserialization के लिए मैं निम्नलिखित SerializationBinder का इस्तेमाल किया है कक्षा:

public class MyBinder : SerializationBinder 
{ 
    public override Type BindToType(string assemblyName, string typeName) 
    { 
     if (assemblyName.Equals(
       "ConsoleApplication14, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")) 
     { 
      if (typeName.Equals("ConsoleApplication14.MyOuterClass")) 
       return typeof(ConsoleApplication14.OtherNamespace.MyOuterClass); 

      if (typeName.Equals("ConsoleApplication14.MyInnerClass")) 
       return typeof(ConsoleApplication14.OtherNamespace.MyInnerClass); 
     } 

     if (assemblyName.Equals("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")) 
     { 
      if (typeName.Equals(
        "System.Collections.ObjectModel.Collection`1[[ConsoleApplication14.MyInnerClass, ConsoleApplication14, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]")) 
       return typeof(Collection<ConsoleApplication14.OtherNamespace.MyInnerClass>); 

      if (typeName.Equals(
        "System.Collections.Generic.List`1[[ConsoleApplication14.MyInnerClass, ConsoleApplication14, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]")) 
       return typeof(List<ConsoleApplication14.OtherNamespace.MyInnerClass>); 

      if (typeName.Equals(
        "System.Lazy`1[[System.Collections.ObjectModel.Collection`1[[ConsoleApplication14.MyInnerClass, ConsoleApplication14, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")) 
       return typeof(Lazy<Collection<ConsoleApplication14.OtherNamespace.MyInnerClass>>); 

      //I THINK, MAYBE THIS 'IF' CONDITION IS THE PROBLEM, BUT DONT KNOW HOW TO FIX THIS. 
      if (typeName.Equals(
        "System.Lazy`1+Boxed[[System.Collections.ObjectModel.Collection`1[[ConsoleApplication14.MyInnerClass, ConsoleApplication14, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")) 
       return typeof(Lazy<Collection<ConsoleApplication14.OtherNamespace.MyInnerClass>>); 
     } 

     return Type.GetType(String.Format("{0}, {1}", typeName, assemblyName)); 
    } 
} 

क्रमबद्धता और MyCustomClass की वस्तु की Deserialization:

public static void Main(string[] args) 
    { 
     //----------------Object Creation---------------------- 
     var objToSerialize = new MyOuterClass 
          { 
           CollectionOfInnerObj = 
            new Lazy<Collection<MyInnerClass>>(
            () => new Collection<MyInnerClass> 
              { 
               new MyInnerClass 
               { 
                StringInInnerClass = "a" 
               }, 
               new MyInnerClass 
               { 
                StringInInnerClass = "aa" 
               }, 
              }) 
          }; 
     //------------------------------------------------------ 

     //---------------------Serialization--------------------- 
     using (var stream = File.Create("E:\\tempFile.tmp")) 
     { 
      var binaryFormatter = new BinaryFormatter(); 

      binaryFormatter.Serialize(stream, objToSerialize); 

      stream.Close(); 
     } 
     //------------------------------------------------------ 

     //-------------------DeSerialization-------------------- 
     using (var stream = File.OpenRead("E:\\tempFile.tmp")) 
     { 
      var binaryFormatter = new BinaryFormatter {Binder = new MyBinder()}; 
      var objOfOtherNamespaceClass = (OtherNamespace.MyOuterClass) binaryFormatter.Deserialize(stream); 

      //Getting NullReferenceException when Value property of objOfOtherNamespaceClass.CollectionOfInnerObj is called 
      foreach (OtherNamespace.MyInnerClass stringVal in objOfOtherNamespaceClass.CollectionOfInnerObj.Value) 
       Console.WriteLine(stringVal.StringInInnerClass); 

      stream.Close(); 
     } 
     //----------------------------------------------------- 
    } 

मैं NullReferenceException हो रही है जब deserialized लेज़ी वस्तु की Value संपत्ति कहा जाता है। (यानी जब objOfOtherNamespaceClass.CollectionOfInnerObj.Value कहा जाता है)

कृपया मुझे इस समस्या को हल करने में मदद ...

+0

मुझे याद है, आईएसरोगेट के साथ बाइनरीफॉर्मेटर में एक बग था जब सर्कुलर निर्भरता (डी) क्रमबद्ध ग्राफ में थी और इसे ठीक करने का कोई इरादा नहीं था। मुझे यकीन नहीं है, लेकिन यह व्यवहार समान दिखता है। – TcKs

उत्तर

3

समस्या लाइन पहले से ही आप से प्रकाश डाला है

//I THINK, MAYBE THIS 'IF' CONDITION IS THE PROBLEM, BUT DONT KNOW HOW TO FIX THIS. 
      if (typeName.Equals(
        "System.Lazy`1+Boxed[[System.Collections.ObjectModel.Collection`1[[ConsoleApplication14.MyInnerClass, ConsoleApplication14, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")) 
       return typeof(Lazy<Collection<ConsoleApplication14.OtherNamespace.MyInnerClass>>); 

कृपया

if (typeName.Equals(
       "System.Lazy`1+Boxed[[System.Collections.ObjectModel.Collection`1[[ConsoleApplication14.MyInnerClass, ConsoleApplication14, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")) 
{ 
    return Type.GetType(typeName.Replace("ConsoleApplication14.MyInnerClass", "ConsoleApplication14.OtherNamespace.MyInnerClass")); 
} 
निम्नलिखित के लिए इस कोड को बदलने

टाइप बॉक्सिंग क्लास होना चाहिए, आलसी source code

के अंदर घोषित किया जाना चाहिए
public class Lazy<T> 
{ 

    #region Inner classes 
    /// <summary> 
    /// wrapper class to box the initialized value, this is mainly created to avoid boxing/unboxing the value each time the value is called in case T is 
    /// a value type 
    /// </summary> 
    [Serializable] 
    class Boxed 
    { 
     internal Boxed(T value) 
     { 
      m_value = value; 
     } 
     internal T m_value; 
    } 

इस सहायता की आशा करें।

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