2010-04-05 54 views
3

在其他情况下,有人建议你简单地添加一个SerializationBinder,它从组件类型中删除版本。但是,当使用在签名程序集中找到的类型的泛型集合时,该类型将严格基于程序集进行版本化。反序列化使用不同版本签名程序集编写的泛型的最佳方式是什么?

这是我找到的作品。

internal class WeaklyNamedAppDomainAssemblyBinder : SerializationBinder 
{ 
    public override Type BindToType(string assemblyName, string typeName) 
    { 
     ResolveEventHandler handler = new ResolveEventHandler(CurrentDomain_AssemblyResolve); 
     AppDomain.CurrentDomain.AssemblyResolve += handler; 

     Type returnedType; 
     try 
     { 
      AssemblyName asmName = new AssemblyName(assemblyName); 
      var assembly = Assembly.Load(asmName); 
      returnedType = assembly.GetType(typeName); 
     } 
     catch 
     { 
      returnedType = null; 
     } 
     finally 
     { 
      AppDomain.CurrentDomain.AssemblyResolve -= handler; 
     } 

     return returnedType; 
    } 

    Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
     string truncatedAssemblyName = args.Name.Split(',')[0]; 
     Assembly assembly = Assembly.Load(truncatedAssemblyName); 
     return assembly; 
    } 
} 

然而,导致结合过程中改变全球似乎是相当危险的我。奇怪的事情可能发生,如果序列化发生在多个线程。也许更好的解决方案是做typeName的一些正则表达式操作?

编辑:基于字符串的方法不起作用。泛型显然需要一个完整的强命名类型。如果你问我,真是令人发指。

+0

快速注意:由于我的特殊情况,我无法使用.NET 2.0或更低版本以外的任何类型的序列化。 – 2010-04-05 16:06:49

+0

使用app.config文件中的''应该更安全,不需要代码。 – 2010-04-05 16:14:17

+0

这是在广泛分布的库中使用,因此不能由app.config控制。 – 2010-04-05 16:56:36

回答

2

AssemblyResolve事件仅在常规绑定失败时触发。所以,任何可以通过正常方法解决的问题都将是。只有反序列化操作才有可能触发事件,并且你已经有了一个完全有效的策略来解决这些问题。

我会在程序启动时添加AssemblyResolve事件处理程序并将其留在那里,而不是添加和删除它。这消除了多线程问题的潜在来源。

+0

事件清除不是线程安全的?在这种情况下,也许我应该为我的AssemblyResolve添加一个警戒,以确保它仅用于此程序集。 – 2010-04-05 17:01:40

0

而不是序列化整个集合,你可以遍历它并逐个序列化每个元素?然后你可以使用SerilizationBinder方法。

+0

但是,在这种情况下,确保新字段序列化会增加维护开销。我一直在试图避免手动实现ISerializable。我已经有了自动向后兼容性测试。 – 2010-04-05 16:31:03

0

这应该回答你的问题:SerializationBinder with List<T>

当使用在SerializationBinder.BindToType泛型类型,你需要使用弱类型名称,而不是完全限定的类型名称。

相关问题