我们发布了一个程序,它使用.NET soap格式化程序序列化一个非常复杂的对象。 Soap没有很好地处理涉及的类的新版本,因此我们将切换到二进制格式化程序。
为了处理旧的对象版本,我编写了一个转换器,用于反序列化soap中的对象,并以二进制形式重新序列化。
转换器在切换时使用类的版本,因此我将这些类放在不同的命名空间中以避免与当前版本发生冲突。
问题在于:命名空间显然是使用类序列化的,因此我得到错误:无法将NamespaceA.class强制转换为NamespaceB.class。 (Arrgh!)
这些课程完全相同;唯一的问题是命名空间。如何让框架忽略命名空间?
答案 0 :(得分:2)
根据此新闻组发布的帖子Changing a namespace causes errors when using "BinaryFormatter.Deserialize" to reload object data saved while defined under a different namesapce(sic),您应该查看SerializationBinder类。
但是,我建议您找到一种不同的数据处理方式,因为二进制格式化程序应该用作短期传输包装处理程序,而不是存储处理程序。
你看过protocol buffers作为一个例子吗?
修改:好的,在阅读完您的评论并重新阅读您的问题之后,事实证明您的问题与序列化无关,无论是二进制还是其他方式。
问题显然是你序列化了一个类型A,并尝试反序列化它,或者在反序列化后将它强制转换为类型B,这是一种不同的类型。
这当然不会开箱即用,并且可以轻松复制而不会引入序列化,您只需执行此操作:
public class A { ... } <-- a class with some properties and stuff
public class B { ... } <-- another class, with the same properties and stuff
public void Test()
{
A a = new A();
B b = a; <-- you get the same problem as in your code here
}
有很多方法可以解决这个问题。例如,您可以将Cast操作符实现到其中一个类中,这将使上述代码起作用。
你可以实现一个“克隆”类型的方法,一个采用类型A的对象,构造一个类型为B的新对象,并复制所有的属性和东西。
请注意,XML序列化使用您为其提供的类型作为其根类型,这意味着您可以序列化类型A的对象,并将其反序列化为类型B的对象,前提是您只在给序列化对象时提供B您打算反序列化,并提供此类型具有足够的元数据看起来像A类型的对象。
我有一个控制问题给你,这可能会让我们知道你为什么要这样做:为什么你不能把它反序列化为原始类型并留下它?你为什么要施展它?
答案 1 :(得分:0)
您可能会发现DataContractSerializer和XmlSerializer更宽容。 XmlSerializer几乎适用于任何XML格式。 DataContract还有一些限制(例如它不能很好地适应属性),但仍应适用于您的场景。