2

我正在尝试在 WCF 之外使用 DataContractSerializer 来序列化对象。本例中的对象继承自 CollectionBase 周围的旧通用包装器,例如

[KnownType(typeof(Foo)]
[CollectionDataContract]
class FooCollection : MyCollectionBase<Foo>

[KnownType(typeof(FooCollection)]
[KnownType(typeof(Foo)]
[CollectionDataContract]
class MyCollectionBase<T> : CollectionBase

[DataContract]
class Foo
{
    [DataMember]
    string Name;
    [DataMember]
    string Value;
}

当它被序列化时,我得到以下结构:

<FooCollection xmlns="http://schemas.datacontract.org/ ...>
  <anyType>
    <Name>...</Name>
    <Value>...</Value>
  </anyType>
</ArrayOfAnyType>

在反序列化我得到错误:

System.Runtime.Serialization.SerializationException:来自命名空间http://schemas.datacontract.org/2004/07/MyAssembly的元素 anyType不能将子内容反序列化为对象。请使用 XmlNode[] 反序列化这种 XML 模式。

----> System.Xml.XmlException:预期来自命名空间“http://schemas.datacontract.org/2004/07/MyAssembly”的结束元素“anyType”。从命名空间“http://schemas.datacontract.org/2004/07/MyAssembly”中找到元素“名称”。第 1 行,位置 xxx。

谷歌搜索此错误显示许多人更改了他们的继承层次结构以使序列化工作,或者只是列出该方法的问题。我找不到任何使用 XmlNode[] 反序列化这种 XML 模式的示例。

所以我的问题是:

  1. 有没有办法让 DataContractSerializer 相信存储在底层 ArrayList 中的类型是 Foo 类型?
  2. 如何实现 XmlNode[] 解决方法?
  3. 是使用不受非泛型集合支持的泛型集合的唯一解决方案吗?
4

2 回答 2

2

鉴于您上面的代码,我使用以下代码进行序列化和反序列化:

        var serializer = new DataContractSerializer(typeof(FooCollection));
        IList collection = new FooCollection();
        var foo = new Foo();
        foo.Name = "TestName";
        foo.Value = "Test value";
        collection.Add(foo);
        StringBuilder sb = new StringBuilder();
        StringWriter writer = new StringWriter(sb);
        XmlTextWriter xmlWriter = new XmlTextWriter(writer);

        serializer.WriteObject(xmlWriter, collection);
        Console.WriteLine(sb.ToString());
        var serialized = sb.ToString();

        var reader = new StringReader(serialized);
        var xmlReader = new XmlTextReader(reader);
        var deserialized = serializer.ReadObject(xmlReader);

        return;

使用 .Net 4.0 和 Visual Studio 2010 没有任何问题。如果要更改元素的名称,使其不是“anyType”,可以将 FooCollection 类的 CollectionDataContract 属性更改为:

    [CollectionDataContract(ItemName="Foo")]
于 2012-12-11T04:08:42.687 回答
2

我找到了问题的原因,在我原来的问题中没有显示:MyCollectionBase 实现了 ISerializable。

DataContractSerializer 将在使用任何属性之前使用 ISerializable 实现。它也无法从 ISerializable 推断出合同,因此没有解决anyType反序列化的方法。

这就是 KnownTypeAttribute 不起作用的原因。

于 2012-12-12T00:18:26.830 回答