SerializationBinder与列表< T>列表、SerializationBinder、GT、LT

2023-09-03 00:27:15 作者:-   久而旧之╮。

我试图让在不同版本的我组装的的BinaryFormatter 工作。我想反序列化到实际的类,正是在每一集的版本相同,但在反序列化,因为在序列化的对象包括他们来自的的BinaryFormatter 是来到集名称抱怨它不能找到合适的组件。所以,我创建了一个自定义的 SerializationBinder 的通知的BinaryFormatter 总是反序列化到当前程序集版本。

我的方案作品并能正确反序列化对象,但它不工作,如果我的对象是T,其中T是一种从我的程序集的旧版本序列化的列表。

有没有一些方法,使这项工作列表和其他泛型类型,其中类型参数是一个类从我的组装?

  //对象我想反序列化
类为MyObject
{
     公共字符串名称{获取;集;}
}

//我的粘合剂类
类MyBinder:SerializationBinder
{
    静态字符串assemblyToUse =的typeof(myObject的).Assembly.FullName;
    公众覆盖类型BindToType(字符串的AssemblyName,字符串的typeName)
    {
        变种isMyAssembly = assemblyName.StartsWith(oldAssemblyName);
        VAR assemblyNameToUse = isMyAssembly? assemblyToUse:的AssemblyName;
        变种TN =的typeName +,+ assemblyNameToUse;
        返回Type.GetType(TN);
    }
}


//我的Deserialize方法
静态对象BinaryDeserialize(字符串输入)
{
    VAR ARR = Convert.FromBase64String(输入);
    VAR毫秒=新的MemoryStream(ARR);
    ms.Seek(0,SeekOrigin.Begin);
    变种BF =新的BinaryFormatter();
    bf.Binder =新MyBinder();
    变种物镜= bf.Deserialize(毫秒);

    返回OBJ;
}

静态无效测试()
{
    //这个工程
    //连载(新的MyObject());
    VAR海峡= ReadSerialized_MyObject();
    VAR OBJ = BinaryDeserialize(STR);

    //这不起作用
    //连载(新名单,其中,为MyObject>());
    VAR STR2赛车= ReadSerialized_List_of_MyObject();
    VAR OBJ = BinaryDeserialize(STR2);
}
 

解决方案

如果你连载的名单,其中一个实例; MyClass的>从你的版本1.0.0.0大会,SerializationBinder.BindToType功能会被要求提供这种类型的:

  System.Collections.Generic.List`1 [MyAssembly.MyClass,MyAssembly程序,版本= 1.0.0.0,文化=中性公钥= 12345678901234567890]
 
电商

为了重新映射列表< MyClass的>键入你的版本2.0.0.0程序集,你需要的类型名称改成这样:

  System.Collections.Generic.List`1 [MyAssembly.MyClass,MyAssembly程序]
 

主要的一点要注意的是,该程序集名称不是完全限定。如果您尝试完全限定的程序集名称与2.0.0.0版本号,这是行不通的。

I'm trying to make the BinaryFormatter work across different versions of my assembly. The actual class I want to deserialize to is exactly the same in each assembly version, but on deserialization, because the objects are serialized include the assembly name they came from, the BinaryFormatter is complaining that it can't find the right assembly. So I created a custom SerializationBinder that tells the BinaryFormatter to always deserialize to the current assembly version.

My scheme works and can deserialize objects correctly, but it doesn't work if my object is a List of T, where T was a type serialized from an older version of my assembly.

Is there some way to make this work with Lists and other generic types where the type parameter is a class from my assembly?

//the object i want to deserialize
class MyObject
{
     public string Name{get;set;}
}

//my binder class
class MyBinder : SerializationBinder
{
    static string assemblyToUse = typeof (MyObject).Assembly.FullName;
    public override Type BindToType(string assemblyName, string typeName)
    {
        var isMyAssembly = assemblyName.StartsWith("oldAssemblyName");
        var assemblyNameToUse = isMyAssembly ? assemblyToUse : assemblyName;
        var tn = typeName + ", " + assemblyNameToUse;
        return Type.GetType(tn);            
    }
}


//my deserialize method
static object BinaryDeserialize(string input)
{
    var arr = Convert.FromBase64String(input);
    var ms = new MemoryStream(arr);
    ms.Seek(0, SeekOrigin.Begin);
    var bf = new BinaryFormatter();
    bf.Binder = new MyBinder();
    var obj = bf.Deserialize(ms);

    return obj;
}

static void Test()
{
    //this works
    //serialized(new MyObject());
    var str = ReadSerialized_MyObject();  
    var obj = BinaryDeserialize(str);

    //this doesn't work
    //serialized(new List<MyObject>());
    var str2 = ReadSerialized_List_of_MyObject(); 
    var obj = BinaryDeserialize(str2);
}

解决方案

If you serialized an instance of List< MyClass > from your version 1.0.0.0 assembly, the SerializationBinder.BindToType function will be asked to provide this type:

System.Collections.Generic.List`1[[MyAssembly.MyClass, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=12345678901234567890]]

In order to remap the List< MyClass > type to your version 2.0.0.0 assembly, you need to change the type name to this:

System.Collections.Generic.List`1[[MyAssembly.MyClass, MyAssembly]]

The main point to note, is that the assembly name is not fully qualified. If you try to fully qualify the assembly name with a 2.0.0.0 version number, it will not work.