使用不同程序集版本进行二进制反序列化

28

我有一个项目,使用BinaryFormatter对由字符串和布尔型数据类型组成的结构体集合进行序列化。

序列化/反序列化工作正常,但如果我更改执行操作的程序集,则反序列化失败,因为二进制文件中的头部指示需要 程序集x 而不是 程序集y 来处理数据。

是否可以设置序列化/反序列化为程序集不可知?


我也遇到了同样的问题...很高兴知道它已经得到解决。 - mmr
5个回答

23

通过为格式化器分配自定义的SerializationBinder,您可以控制二进制格式化器如何解析其类型。这样,您不需要处理AppDomain的解析事件,并消除了由此带来的意外副作用的风险。

MSDN上有一个详细的示例。


谢谢,这似乎是最安全的选择 - 特别是如果我将代码移动到不同的程序集中... - Matthew Savage
@mmr:我刚刚测试了一下,已经可以工作了。从答案中的MSDN示例开始,然后修改序列化绑定程序以允许某些程序集版本不匹配。 - SteinNorheim
需要注意的一件事是,如果您有嵌套类型(例如,自定义对象的自定义集合),则需要加载多个程序集...请尝试通过重载的BindToType方法进行步进。 - Matthew Savage
换个角度怎么样?当您想控制在序列化时存在于二进制文件中的程序集时,该怎么办? - jm.

12

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

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

它可以工作,但数据应该使用相同的方法进行序列化和反序列化。 - dariol

5

通过Hook 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

这是一篇关于.NET应用程序中线程池的文章。线程池是一个管理并发性的机制,它可以在需要时分配和重用线程。在.NET中,线程池是由CLR(公共语言运行库)提供的。本文探讨了如何使用线程池来提高应用程序的性能和可伸缩性。


我原本打算使用这个,但是我可以看到在并发执行时可能会出现严重的失败情况。 - Matthew Savage

3

有其他的(二进制)序列化引擎(比如这个),它们不依赖程序集。


1

GAC(全局程序集缓存)是您的首要资源,允许不同版本的程序集共存。但这并不能解决问题,除非您的应用程序也具备版本兼容性。二进制序列化具有多个功能来处理版本兼容性序列化。阅读MSDN library article中的相关内容。


感谢您提供的GAC建议,但是我希望尽量减少应用程序的占用空间,让所有内容都从它自己的文件夹中运行。 - Matthew Savage

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接