为什么我不能反序列化KnownType'd anyType?

时间:2012-12-07 01:25:25

标签: c# .net arraylist datacontractserializer

我正在尝试在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模式。

     

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

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

所以我的问题是:

  1. 有没有办法说服DataContractSerializer存储在底层ArrayList中的类型是Foo类型?
  2. 如何实施XmlNode []解决方法?
  3. 是唯一使用非通用集合支持的通用集合的解决方案吗?

2 个答案:

答案 0 :(得分: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")]

答案 1 :(得分:2)

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

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

这就是KnownTypeAttribute无效的原因。