使用不同版本的已签名程序集编写的泛型反序列化的最佳方法是什么?

时间:2010-04-05 15:53:57

标签: c# serialization binaryformatter serializationbinder

在其他情况下,有人建议您只需添加一个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进行一些正则表达式操作?

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

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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