1

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

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已创建但始终为空!在反序列化过程中我没有收到错误。

我尝试使用 a DataContractResolver,但该函数ResolveName从不调用ClassAor ClassB

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

在这 2 种情况下,ResolveName仍然不要求ClassAClassB

我尝试使用从函数派生的类IDataContractSurrogate并转换函数中的类型,GetDataContractType并且该函数不调用ClassAand ClassB


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

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

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

4

1 回答 1

1

但是现在当我尝试反序列化 XML 时,集合ListOfA已创建但始终为空!在反序列化过程中我没有收到错误。

有关数据合同版本控制的 msdn 文档中,您可以找到有关为什么ListOfA为空的信息。您调整后的版本的反序列化引擎无法解释ClassAClassB因此丢弃此数据。

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

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

由于您没有在构造函数的已知数据类型参数中指定ClassA和,因此不会为它们调用。有关已知数据类型的更多信息,请查看 msdn 文档。这意味着为了正确反序列化这些旧类,您仍然需要包含它们以实现向后兼容性。ClassBDataContractSerializerResolveName()

于 2012-11-20T15:20:54.523 回答