在DataContractSerializer中将删除的类型反序列化为新类型(旧基类)

时间:2012-11-20 14:33:22

标签: .net vb.net datacontractserializer

这是我的旧类图(简化)。

public class Main
    Public Property ListOfA As ClassACollection
End Class

Public Class ClassBase
End Class

Public Class ClassA
  Inherits ClassBase
End Class

Public Class ClassACollection
    Inherits System.Collections.ObjectModel.Collection(Of ClassA)
End Class

Public Class ClassB
  Inherits ClassBase
End Class

Public Class ClassBCollection
    Inherits System.Collections.ObjectModel.Collection(Of ClassB)
End Class

当我使用Main序列化类DataContractSerializer时,我得到了这样的XML:

<Main>
  <ListOfA>
    <ClassA>
      .....
    </ClassA>
    <ClassA>
      .....
    </ClassA>
  </ListOfA>
</Main>

最近我删除了ClassAClassB,因为它们完全相同!我删除了两个集合以替换它们:

public class Main
    Public Property ListOfA As ClassBaseCollection
End Class

Public Class ClassBaseCollection
    Inherits System.Collections.ObjectModel.Collection(Of ClassBase)
End Class

但是现在当我尝试反序列化XML时,集合ListOfA已创建但始终为空!反序列化期间没有出错。

我尝试使用DataContractResolver,但函数ResolveName永远不会调用ClassAClassB

Dim dc As New Runtime.Serialization.DataContractSerializer(GetType(Main), Nothing, Integer.MaxValue, False, True, Nothing, New MyResolver())

Private Class MyResolver
    Inherits Runtime.Serialization.DataContractResolver

    Public Overrides Function ResolveName(typeName As String, typeNamespace As String, declaredType As System.Type, knownTypeResolver As System.Runtime.Serialization.DataContractResolver) As System.Type
      If typeName.Equals("ClassA") OrElse typeName.Equals("ClassB") Then
        Return GetType(ClassBase)
      Else
        'Defer to the known type resolver
        Return knownTypeResolver.ResolveName(typeName, typeNamespace, Nothing, Nothing)
      End If
  End Function
End Class

DataContractResolver能够做到我想要的好方法吗? 如果是,我需要其他东西才能使DataContractResolver工作吗?

感谢您的帮助!


更新 我在项目中添加了ClassAClassB来进行以下测试:
  - 我试图将它们作为已知数据类型放在DataContractSerializer构造函数中   - 我在ClassBaseCollection`上尝试了KnownTypeAttribute

在这两种情况下,仍然没有为ResolveNameClassA调用ClassB

我尝试使用从IDataContractSurrogate派生的类并转换函数GetDataContractType中的类型,此函数不会调用ClassAClassB


更新#2: 最后,我没有找到任何办法去做我想要的。我需要查看文件版本,并在序列化之前用XML中的新标记替换旧标记。防爆。 :

data = data.Replace("<ClassA>", "<ClassBase>")
...

这不是我第一个问题的答案,而是一种解决方法。

1 个答案:

答案 0 :(得分:1)

  

但是现在当我尝试反序列化XML时,集合ListOfA就是   创造但总是空的!反序列化期间没有出错。

msdn documentation on Data Contract Versioning中,您可以找到有关ListOfA为空的原因的信息。调整后版本的反序列化引擎无法解释ClassAClassB,因此会丢弃此数据。

我认为您使用Data Contract Resolver进行了正确的跟踪。

  

数据合约解析程序允许您配置已知类型   动态。 序列化时需要已知类型或   反序列化数据合同不期望的类型

由于您未在DataContractSerializer constructor的已知数据类型参数中指定ClassAClassB,因此不会为它们调用ResolveName()。有关已知数据类型的更多信息,请check the msdn documentation。这意味着为了正确地反序列化这些旧类,您仍然需要包含它们以实现向后兼容。