带 List的 SerializationBinder
我正在尝试使 BinaryFormatter
在程序集的不同版本中工作。我想要反序列化到的实际类在每个程序集版本中都完全相同,但是在反序列化时,因为序列化的对象包括它们来自的程序集名称,所以 BinaryFormatter
抱怨它不能找到正确的组件。因此,我创建了一个自定义的 SerializationBinder
,它告诉 BinaryFormatter
始终反序列化为当前的程序集版本。
我的方案有效并且可以正确反序列化对象,但如果我的对象是 T 列表,则它不起作用,其中 T 是从旧版本的程序集序列化的类型。
有没有某种方法可以使其与列表和其他泛型类型一起使用,其中类型参数是我的程序集中的类?
//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);
}
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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您序列化了 List< 的实例我的班级>从版本 1.0.0.0 程序集中,将要求 SerializationBinder.BindToType 函数提供此类型
:我的班级>类型为您的版本 2.0.0.0 程序集,您需要将类型名称更改为: 需要
注意的要点是程序集名称不是完全限定的。如果您尝试使用 2.0.0.0 版本号完全限定程序集名称,它将不起作用。
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:
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:
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.
应用程序 A 创建一个序列化二进制格式化程序文件“SerializedList.bin”,其中包含 List(Result),其中 Result 是可序列化对象。
现在应用程序 B 想要反序列化文件并加载到 List(Result) 对象中。
这就是我让它工作的方式..
参考:http://social.msdn.microsoft.com/forums/en-US/netfxremoting/thread/eec2b7a6-65f8-42d1-ad4f-409f46bdad61
应用程序程序集名称为“Serialize”< br>
应用程序 B 程序集名称为“DeSerialize”
应用程序 A 代码(序列化):
}
一些结果对象:
应用程序 B 代码(反序列化):
}
Application A creates a Serialized Binary formatter file "SerializedList.bin" which contains List(Result) where Result is the Serializable object.
Now Application B wants to DeSerialize the file and load into List(Result) object.
This is how I got it working..
Reference: http://social.msdn.microsoft.com/forums/en-US/netfxremoting/thread/eec2b7a6-65f8-42d1-ad4f-409f46bdad61
Application A Assembly Name is "Serialize"
Application B Assembly Name is "DeSerialize"
Application A Code(Serialize):
}
Some Result Object:
Application B Code (DeSerialize):
}
只需处理 AppDomain.AssemblyResolve 事件并在调用 Type.GetType 方法时返回所需的程序集即可。就这么简单!
Just handle
AppDomain.AssemblyResolve
event and return the desired assembly when callingType.GetType
method. That's as simple as that!您还可以在 BindToType 函数中使用更简单的构造,如下所示:
如果您的类型定义不正确,最后一个参数“true”将给您错误消息(带有跟踪)。以后调试的时候会节省很多时间。
You can also use more simple construction like this in BindToType function:
Last parameter 'true' will give you error message (with trace) if your type definition is incorrect. It will save you a lot of time in debugging later.