将对象反序列化为现在已签名和版本化的程序集

时间:2009-04-23 08:02:23

标签: .net serialization strongname

我曾经使用BinaryFormatter(c#)序列化树视图。正是这样做并且包含所有可序列化类的程序集现在具有强名称并且已签名并且还获得了新版本号(但是,实现没有更改)。

当我尝试反序列化byte []数组时,行

(TreeViewData)binaryFormatter.Deserialize(memoryStream);

产生ArgumentNullException。 (参数名称:类型)

我认为版本号是问题,所以我实现了一个自己的Binder。我覆盖了BindToType方法,并确保更正版本并返回正确的类型。

然而,在目前,程序离开了BindToType方法,我仍然得到上面提到的异常。

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:12)

您可以使用SerializationBinder来解决此问题:

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

然后

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

Voila,您的旧序列化对象可以使用此格式化程序进行反序列化。如果类型也发生了变化,您可以使用SerializationSurrogate将旧类型反序列化为新类型。

正如其他人所提到的那样,进行自己的序列化而不是依赖IFormatter是一个好主意,因为您可以更好地控制版本控制和序列化大小。

答案 1 :(得分:3)

你可以尝试使用序列化代理,但如果没有我们可以重现的东西,很难给出一个合适的答案。

然而,根本问题在于BinaryFormatter在组装等方面非常非常脆弱。哎呀,它甚至脆弱within an assembly

听起来TreeViewData是基于树的,所以我想知道xml是否会更好(即更容忍版本)选项。如果要考虑效率,可以使用自定义二进制格式(如protobuf-net),它们提供高性能,版本容忍,可移植的二进制序列化。如果您的数据已经序列化......我想知道是否可能是时候改变轨道了?尝试使用旧的程序集对数据进行反序列化,并切换到更强大的序列化策略。

答案 2 :(得分:1)

我的建议是永远不要将内置序列化用于持久存储。如果由于其他原因将来您将需要从另一种语言读取和编写您的文件格式,请始终编写自己的代码。