Tuesday, October 10, 2017

SerializationException: Could not find type 'System.Collections.Generic.List`1 in c# unity3d

Leave a Comment

I am trying to serialize and deserialize an object in c# unity3d. For that I am using the below code. But I am getting an error mentioned below.

Error: SerializationException: Could not find type 'System.Collections.Generic.List`1[[ABC, Assembly-CSharp, Version=1.0.2.18931, Culture=neutral, PublicKeyToken=null]]'.

This is not happening while I serialize the object save to file and load it from file while I am playing the game with out stopping the game.

But the error occurs if I stop the game and change any line of code ( irrelevant to serialization and Deserialization )and load data from file saved previously and trying to deserialize I am getting an SerializationException.

I am using visual studio editor and unity3d version is 5.5.4

I may be missing something very simple thing. could someone help me in resolving this.

Thanks.

public static string SerializeObject<T>(T objectToSerialize) {     BinaryFormatter bf = new BinaryFormatter();     MemoryStream memStr = new MemoryStream();      try     {         bf.Serialize(memStr, objectToSerialize);         memStr.Position = 0;          return Convert.ToBase64String(memStr.ToArray());     }     finally     {         memStr.Close();     } }  public static T DeserializeObject<T>(string str) {     BinaryFormatter bf = new BinaryFormatter();     bf.Binder = new CurrentAssemblyDeserializationBinder();     byte[] b = Convert.FromBase64String(str);     MemoryStream ms = new MemoryStream(b);      try     {         return (T)bf.Deserialize(ms);     }     finally     {         ms.Close();     } } 

Class I am using:

    [Serializable]    public class ABC : ISerializable   {     public SerializableDictionary<int, ExampleClass> a = new SerializableDictionary<int, ExampleClass>();      public GameObject b;     public GameObject c;     public bool d = false;     public ABC e;     public int f;     public string g = "";     public int h = -1;     public int i = -1;     public int j = -1;     public string k = "default";     public XYZ l = XYZ.P;   }      [Serializable]     public enum XYZ     {         P,         Q     }       [Serializable()]     public class ABCListWrapper : ISerializable     {      public List<ABC> abcMappings = new List<ABC>();     public string version = "1.53";     public float interval;     }       //Serilization      abcLW = new ABCListWrapper();     abcW = getABCListWObj();     string abcWString = SerializeObject(abcW);     File.WriteAllText(Application.streamingAssetsPath + "/filename.json", abcWString);       //Deserilization call      ABCListWrapper l = new ABCListWrapper();     string l_1 = File.ReadAllText(Application.streamingAssetsPath + "/filename.json");     l =  DeserializeObject<ABCListWrapper>(l_1); 

Attempt to resolve the issue:

public sealed class CurrentAssemblyDeserializationBinder : SerializationBinder {     public override Type BindToType(string assemblyName, string typeName)     {         Version assemVer1 = Assembly.GetExecutingAssembly().GetName().Version;         Debug.Log("ASSEM VER: " + assemVer1 + "--NAME--" + assemblyName + " --OVERAL-- " + Assembly.GetExecutingAssembly().FullName + " --TYPE-- " + typeName );         //assemblyName = Assembly.GetExecutingAssembly().FullName.Replace(assemVer1.ToString(), "1.0.2.23455");         //string assemblyNameCustom = "Assembly-CSharp, Version=1.0.2.18931, Culture=neutral, PublicKeyToken=null";          bool isList = false;          if (typeName.Contains("List`1"))             isList = true;         // other generics need to go here          if (isList)             return Type.GetType(string.Format("System.Collections.Generic.List`1[[{0}, {1}]]", "ABC", "Assembly-CSharp, Version=1.0.2.18931, Culture=neutral, PublicKeyToken=null"));         else             return Type.GetType(string.Format("{0}, {1}", assemblyName, typeName));      }  } 

But I am getting the same exception and the log in BindToType is never printed. So it means the function BindToType in the SerilizationBinder.

2 Answers

Answers 1

The binary formatter is storing the assembly version information along with the serialized type. So even when the type is not changed, the serialization/deserialization changes as soon as the assembly is updated.

See this related Q/A for details: Binary Deserialization with different assembly version and the relevant MSDN article.

Normally I would close-vote this as a duplicate, but I can't because of the open bounty, so I decided to answer instead ;)

Answers 2

For fast binary serialization Protocol Buffers can be good option. Also it should resolve compatibility issues (you can control fields order/exclusion manually)

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment