I want to Serialize and DeSerialize an object that contains a Lazy Collection some custom objects.
Usually everything works fine, but if the namespaces of the classes used for serialization change, this problem occurs.
I wrote a SerializationBinder to point to the right classes when deserializing. But for some reason, I am not getting deserialized values.
The following code snippet explains the problem I am getting;
Classes used for serialization:
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>>)); } } }
The same classes are used for deserialization, but only the namespace changes to ConsoleApplication14.OtherNamespace
For such deserialization to work, I used the following SerializationBinder class:
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>>);
Serializing and deserializing a MyCustomClass object:
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(); } //----------------------------------------------------- }
I get a NullReferenceException when the Value property of a deserialized Lazy object property is called. (i.e. when objOfOtherNamespaceClass.CollectionOfInnerObj.Value is called)
Please help me solve this problem ...