Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
400 views
in Technique[技术] by (71.8m points)

c# - SerializationBinder with List<T>

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);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...