Deserialize object into assembly that is now signed and versioned

我怕爱的太早我们不能终老 提交于 2019-12-18 21:49:12

问题


I used to serialize a treeview with the BinaryFormatter (c#). The Assembly that did just that and which contains the all the serializable classes has now a strong name and is signed and also got a new version number (however, implementation didn't change).

When I try to deserialize the byte[] array, the line

(TreeViewData)binaryFormatter.Deserialize(memoryStream);

produces an ArgumentNullException. (Parametername: type)

I thought the versionnumber is the problem, so I implemented an own Binder. I overwrote the BindToType method and made sure that the version is corrected and the correct type is returned.

However, at the very moment, the program leaves the BindToType method, I still get the exception mentioned above.

How do I fix this?


回答1:


You can use a SerializationBinder to solve this:

private class WeakToStrongNameUpgradeBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        try 
        {
            //Get the name of the assembly, ignoring versions and public keys.
            string shortAssemblyName = assemblyName.Split(',')[0];
            var assembly = Assembly.Load(shortAssemblyName);
            var type = assembly.GetType(typeName);
            return type;
        }
        catch (Exception)
        {
            //Revert to default binding behaviour.
            return null;
        }
    }
}

Then

var formatter = new BinaryFormatter();
formatter.Binder = new WeakToStrongNameUpgradeBinder();

Voila, your old serialized objects can be deserialized with this formatter. If the type have also changed you can use a SerializationSurrogate to deserialize the old types into your new types.

As others have mentioned, doing your own serialization rather than relying on IFormatter is a good idea as you have much more control over versioning and serialized size.




回答2:


You could try using a serialization surrogate, but without something we can reproduce it will be hard to give a decent answer.

The fundamental problem, however, is that BinaryFormatter is simply very, very brittle when it comes to things like assemblies. Heck, it is brittle enough even within an assembly.

It sounds like TreeViewData is tree based, so I wonder whether xml would have been a better (i.e. more version tolerant) option. If efficiency is a concern, there are custom binary formats (like protobuf-net) that offer high performance, version tolerant, portable binary serialization. If your data is already serialized... I wonder if it might be time to change track? Try using the old assembly to deserialize the data, and switch to a more robust serialization strategy.




回答3:


My recommendation is to never use the builtin serializes for your persistent storage. Always code your own if for no other reason someday in the future you will need to read and write your file formats from another language.



来源:https://stackoverflow.com/questions/780739/deserialize-object-into-assembly-that-is-now-signed-and-versioned

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!