不同程序集版本的二进制反序列化

Posted

技术标签:

【中文标题】不同程序集版本的二进制反序列化【英文标题】:Binary Deserialization with different assembly version 【发布时间】:2010-10-05 01:43:44 【问题描述】:

我有一个项目,它使用 BinaryFormatter 序列化具有字符串和布尔的结构集合?数据类型。

序列化/反序列化工作正常,但是如果我要更改完成工作的程序集,它无法反序列化,因为二进制文件中的标头表明它需要 Assembly x 而不是 Assembly y 来处理数据.

是否可以将序列化/反序列化设置为与程序集无关?

【问题讨论】:

我遇到了同样的问题...很高兴知道它已得到解决。 【参考方案1】:

您可以通过将自定义 SerializationBinder 分配给格式化程序来控制二进制格式化程序如何解析其类型。这样一来,您就不需要弄乱 AppDomain 的解析事件,并且消除了由此产生的意外副作用的风险。

MSDN有详细示例。

【讨论】:

谢谢,这似乎是最安全的选择 - 特别是如果我将代码移动到不同的程序集中... @mmr:我刚刚对其进行了测试并使其正常工作。从答案中的 MSDN 示例开始,并修改序列化绑定器以允许某些程序集版本不匹配。 您需要注意的一件事是,如果您有嵌套类型(例如自定义对象的自定义集合),您将需要加载多个程序集...尝试逐步执行重载 BindToType 方法。 换个方式怎么样?当您想控制二进制文件中的程序集时如何进行序列化?【参考方案2】:

您可以更改 BinaryFormatter 属性 AssemblyFormat 以使序列化独立于程序集版本。

// Example
var binFormat = new BinaryFormatter();
binFormat.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;

【讨论】:

它可以工作,但数据应该使用相同的方法进行序列化和反序列化。【参考方案3】:

挂钩 AppDomain.OnAssemblyResolve 事件并修复程序集名称

private System.Reflection.Assembly OnAssemblyResolve( System.Object sender, System.ResolveEventArgs reArgs )

     foreach( System.Reflection.Assembly assembly in System.AppDomain.CurrentDomain.GetAssemblies() ) 
     
         System.Reflection.AssemblyName assemblyName = assembly.GetName();
         if( assemblyName.FullName == reArgs.Name ) 
         
              return( assembly );
         
     

来源:http://osdir.com/ml/windows.devel.dotnet.clr/2003-12/msg00441.html

【讨论】:

我原本打算使用它,但是我可以看到并发执行时可能出现严重失败的极端情况..【参考方案4】:

存在不依赖于程序集的替代(二进制)序列化引擎 (like this)。

【讨论】:

【参考方案5】:

GAC 是您的第一个资源,它允许不同版本的程序集并行共存。但这并不能真正解决任何问题,除非您的应用程序也具有版本容错性。二进制序列化有几个特性来处理版本兼容的序列化。在这个 MSDN library article 中阅读它。

【讨论】:

感谢 GAC 的建议,但是我尽量不给应用程序留下沉重的足迹,让一切都从自己的文件夹中运行。

以上是关于不同程序集版本的二进制反序列化的主要内容,如果未能解决你的问题,请参考以下文章

反序列化异常:找不到程序集

如何反序列化 .net 核心中的 json 数据集

不同命名空间的对象二进制反序列化问题

解决反序列化(Deserialize)无法找到程序集的错误

使用不同版本名称空间序列化/反序列化 XSD 的方法?

序列化和反序列化-刘丁