不同程序集版本的二进制反序列化
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 的建议,但是我尽量不给应用程序留下沉重的足迹,让一切都从自己的文件夹中运行。以上是关于不同程序集版本的二进制反序列化的主要内容,如果未能解决你的问题,请参考以下文章