【问题标题】:Serialization problem: Different namespaces (.NET)序列化问题:不同的命名空间(.NET)
【发布时间】:2025-11-25 00:30:01
【问题描述】:

我们发布了一个使用 .NET soap 格式化程序序列化一个非常复杂的对象的程序。 Soap 不能很好地处理所涉及的类的新版本,因此我们正在切换到二进制格式化程序。

为了处理旧的对象版本,我编写了一个转换器,它在soap中反序列化对象,并在二进制中重新序列化它。

转换器使用切换时类的版本,因此我将这些类放在不同的命名空间中以避免与当前版本冲突。

问题是:命名空间显然是用类序列化的,所以我收到错误:无法将 NamespaceA.class 强制转换为 NamespaceB.class。 (啊!)

类完全相同;唯一的问题是名称空间。如何让框架忽略命名空间?

【问题讨论】:

  • 这是否就像在说“两辆车一模一样,只是一辆是红色的,另一辆是蓝色的,其中一辆是福特,另一辆是沃尔沃”?
  • 这更像是说一辆红色沃尔沃是经销商 A 卖的,另一辆红色沃尔沃是经销商 B 卖的,所以它们是“不同的”。
  • 不是真的,@alankdkd。命名空间是类名的一部分,@Lesse 是对的。
  • 在这种情况下,它是类中不需要和不需要的部分。我通过避免它来“解决”了这个问题:我让转换器成为一个单独的应用程序,所以我可以使用相同的命名空间。而且……它奏效了!感谢 LASSE 和 MATHEW 的建议!

标签: .net serialization soap namespaces


【解决方案1】:

根据此新闻组发布的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
}

有很多方法可以处理这个问题。例如,您可以在其中一个类中实现强制转换运算符,这将使上述代码正常工作。

你可以实现一个“克隆”类型的方法,它接受一个类型 A 的对象,构造一个类型 B 的新对象,并复制所有的属性和东西。

注意 XML 序列化使用你给它的类型作为它的根类型,这意味着你可以序列化一个 A 类型的对象,并将它反序列化为一个 B 类型的对象,前提是你只给序列化对象 B您打算反序列化,并提供此类型具有足够的元数据以看起来像 A 类型的对象。

我有一个控制问题要问你,这可能会让我们知道你为什么要这样做:你为什么不能将它反序列化为原始类型并让它保持不变?为什么一定要投呢?

【讨论】:

  • 问题是将(NamespaceA 的)反序列化对象分配给 NamespaceB 中名称类的变量。反序列化似乎是成功的,因此新的活页夹在这里无济于事。还是谢谢。
  • 反序列化为 Object 类型的变量有效。问题是将它放入正确类的变量中,以便我可以使用二进制格式化程序重新序列化它。看来我会在使用协议缓冲区时遇到同样的问题。
  • Lasse,我最终做了类似的事情;使用相同命名空间的单独应用程序,因此没有冲突。 (最初我希望转换器在同一个应用程序中的 DLL 中,并且需要不同的命名空间来防止每个类的旧/新版本之间的冲突。)结果证明这比需要单独处理每个类成员的解决方案更简单(有很多)。再次感谢您的建议。
【解决方案2】:

您可能会发现DataContractSerializerXmlSerializer 更宽容。 XmlSerializer 适用于几乎任何 XML 格式。 DataContract 有更多限制(例如它不能很好地与属性配合使用),但仍应适用于您的场景。

【讨论】: