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

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

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

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

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

 [assembly:TypeForwardedTo(typeof(TheType))] 

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

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

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

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