Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 487
djkpA Avatar asked Sep 09 '17 05:09

djkpA


1 Answers

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 ;)

like image 88
grek40 Avatar answered Oct 21 '22 10:10

grek40