带有List 的SerializationBinder

我正在尝试使BinaryFormatter在我的程序集的不同版本中工作。 我希望反序列化的实际类在每个程序集版本中完全相同,但在反序列化时,因为序列化对象包括它们来自的程序集名称,所以BinaryFormatter抱怨它无法找到正确的程序集。 所以我创建了一个自定义的SerializationBinder ,它告诉BinaryFormatter总是反序列化到当前的程序集版本。

我的方案工作正常,可以反序列化对象,但如果我的对象是T的列表,它不起作用,其中T是从我的程序集的旧版本序列化的类型。

是否有一些方法可以使用Lists和其他generics类型,其中type参数是我的程序集中的类?

 //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()); var str2 = ReadSerialized_List_of_MyObject(); var obj = BinaryDeserialize(str2); } 

如果从版本1.0.0.0程序集序列化List 的实例,将要求SerializationBinder.BindToType函数提供此类型:

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

要将List 类型重新映射到版本2.0.0.0程序集,您需要将类型名称更改为:

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

需要注意的要点是,程序集名称不是完全限定的。 如果您尝试使用2.0.0.0版本号完全限定程序集名称,则它将不起作用。

应用程序A创建一个序列化二进制格式化程序文件“SerializedList.bin”,其中包含List(Result),其中Result是Serializable对象。 现在,应用程序B想要对文件进行DeSerialize并加载到List(Result)对象中。 这就是我的工作方式..

参考: http : //social.msdn.microsoft.com/forums/en-US/netfxremoting/thread/eec2b7a6-65f8-42d1-ad4f-409f46bdad61

应用程序组件名称为“Serialize”
应用程序B程序集名称为“DeSerialize”

应用程序代码(序列化):

 namespace Serialize { class Program { static void Main(string[] args) { List result = ;//Get From DB IFormatter formatter = new BinaryFormatter(); Stream sStream = new FileStream( "SerializedList.bin", FileMode.CreateNew, FileAccess.Write, FileShare.None); formatter.Serialize(sStream, result); sStream.Close(); } } 

}

一些结果对象:

 [Serializable] public class Result { public decimal CONTACT_ID { get; set; } public decimal INSTITUTION_NBR { get; set; } } 

申请B代码(DeSerialize):

 namespace DeSerialize { class Program { static void Main(string[] args) { IFormatter formatter = new BinaryFormatter(); string fromTypeName = "System.Collections.Generic.List`1[[Serialize.Result, Serialize, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"; string fromTypeName1 = "Serialize.Result"; string toTypename = "System.Collections.Generic.List`1[DeSerialize.Result]"; string toTypename1 = "DeSerialize.Result"; string toTypeAssemblyName = Assembly.GetExecutingAssembly().FullName; DictionarySerializationBinder dic = new DictionarySerializationBinder(); dic.AddBinding(fromTypeName, toTypename); dic.AddAssemblyQualifiedTypeBinding(fromTypeName1, toTypename1, toTypeAssemblyName); formatter.Binder = dic; Stream dStream = new FileStream( "SerializeList.bin", FileMode.Open, FileAccess.Read, FileShare.Read); List listDS = (List)formatter.Deserialize(dStream); dStream.Close(); } } sealed class DictionarySerializationBinder : SerializationBinder { Dictionary _typeDictionary = new Dictionary(); public override Type BindToType(string assemblyName, string typeName) { Type typeToReturn; if (_typeDictionary.TryGetValue(typeName, out typeToReturn)) { return typeToReturn; } else { return null; } } public void AddBinding(string fromTypeName, string toTypeName) { Type toType = Type.GetType(toTypeName); if (toType == null) { throw new ArgumentException(string.Format( "Help, I could not convert '{0}' to a valid type.", toTypeName)); } _typeDictionary.Add(fromTypeName, toType); } public void AddAssemblyQualifiedTypeBinding(string fromTypeName, string toTypeName, string toTypeAssemblyName) { Type typeToSerializeTo = GetAssemblyQualifiedType(toTypeAssemblyName, toTypeName); if (typeToSerializeTo == null) { throw new ArgumentException(string.Format( "Help, I could not convert '{0}' to a valid type.", toTypeName)); } _typeDictionary.Add(fromTypeName, typeToSerializeTo); } private static Type GetAssemblyQualifiedType(string assemblyName, string typeName) { return Type.GetType(String.Format("{0}, {1}", typeName, assemblyName)); } } 

}