Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

InvalidCastException when serializing and deserializing

I have this code:

public byte[] SerializeToBlob()
{
    using (var buffer = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(buffer, this);
        buffer.Position = 0;
        return buffer.ToArray();
    }
}

public static ActionData DeserializeFromBlob(byte[] state)
{
    using (var buffer = new MemoryStream(state))
    {
        var formatter = new BinaryFormatter();
        var result = formatter.Deserialize(buffer);
        return (ActionData) result;
    }
}

And am calling it as follows:

byte[] actionDataBlob = ad.SerializeToBlob();
var ad1 = ActionData.DeserializeFromBlob(actionDataBlob);

However, I get an InvalidCastException when it tries to cast the deserialized object to its type:

[A]ActionData cannot be cast to [B]ActionData. Type A originates from 'XXXX.XXXX.Auditing, Version=1.0.76.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Users\Craig\AppData\Local\Temp\Temporary ASP.NET Files\root\5d978e5b\ffc57fe1\assembly\dl3\2b1e5f8f\102c846e_9506ca01\XXXX.XXXX.Auditing.DLL'. Type B originates from 'XXXX.XXXX.Auditing, Version=1.0.76.0, Culture=neutral, PublicKeyToken=null' in the context 'LoadNeither' at location 'F:\Visual Studio Projects\XXXXXXXXX\source\XXXX.XXXX.SilverlightClient.Web\bin\XXXX.XXXX.Auditing.dll'.

(XXXX.XXXX is there to obscure the client's name)

What gives?

I've now asked a related question here:

How should I serialize some simple auditing data for storing in a SQL table?

like image 879
Craig Shearer Avatar asked Jul 17 '09 07:07

Craig Shearer


2 Answers

You have loaded the same assembly twice, in different loader contexts. E.g. you happened to load the XXX.Auditing with Assembly.LoadFrom() first, and then some other (or your) assembly loaded it normally. In fact, the binary deserializer could be the one who loaded the assembly a second time, though I wouldn't know why (no experience with ASP.NET).

like image 148
Anton Tykhyy Avatar answered Oct 12 '22 22:10

Anton Tykhyy


It sounds to me like you have the same class in different assemblies (or web applications). BinaryFormatter includes the type metadata in the serialization, which means that only the exact same assembly will do. 2 solutions:

  • put this type in a dll, and reference that single dll in both places
  • use a contract-based serializer

Personally I would choose the second for a huge number of reasons not just limited to this one. Likely choices:

  • XmlSerializer (xml; serializes public fields and properties; "tree" only)
  • DataContractSerializer (xml; serializes marked fields and properties (public or private); "tree" or "graph")
  • protobuf-net (binary; serializes marked fields and properties (public or private); "tree" only)

Which is best depends on the scenario.

like image 29
Marc Gravell Avatar answered Oct 13 '22 00:10

Marc Gravell