C#反序列化已移动或已重命名的类

时间:2009-09-23 10:02:17

标签: c# serialization binary

如果我在名为“AssemblyA”的程序集中有一个名为“MyClass”的类,并使用.NET的BinaryFormatter将其序列化为一个文件。然后将“MyClass”的代码移动到名为“AssemblyB”的程序集中,并尝试反序列化该文件,我得到以下“System.TypeLoadException”异常:

  

无法从程序集'AssemblyA,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'加载类型'AssemblyA.MyClass'。

我有什么方法可以表明该课程已移至AssemblyB吗?通过某种属性?或者是否可以将序列化文件修改为预处理步骤,以将AssemblyA.MyClass中的所有引用更改为AssemblyB.MyClass?最后,如果这些选项都不可能,是否可以绕过尝试反序列化该类并继续反序列化其余数据?

1 个答案:

答案 0 :(得分:6)

如果您已移动它,请添加对它现在所在的dll的引用,并使用TypeForwardedToAttribute

[assembly:TypeForwardedTo(typeof(TheType))]

这对于某些请求(包括BinaryFormatter IIRC)寻找类型以在新程序集中找到它是足够的。但是,IIRC它只适用于最外层类型(不是嵌套类型,可能不是泛型),你不能重命名它/更改名称空间/等。

重命名是诡计...... BinaryFormatter对于这些事情是众所周知的脆弱。 IMO,它仅适用于在两个紧密耦合的系统之间串行化瞬态数据(例如,在同一进程中的两个AppDomain之间进行交换;当用于存储时,或者在可能不同步的系统之间进行交换时,它可以是一场噩梦。

可能为时已晚,但我建议使用基于合同的序列化程序(而不是基于类型的序列化程序);任何XmlSerializerDataContractSerializer(只要你使用[DataContract] / [DataMember]属性)等等。如果你想要快速二进制,protobuf-net会做得很好工作(如果需要,可以挂钩ISerializable。)

另一个可能值得关注的概念是序列化代理,但这是相对困难的。但是IIRC可以让你控制所创建的类型 - 但是你需要为它做一个批次的工作。