首页 文章

为什么't I deserialize a KnownType' d anyType?

提问于
浏览
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模式的任何示例 .

所以我的问题是:

  • 有没有办法说服DataContractSerializer存储在底层ArrayList中的类型是Foo类型?

  • 如何实现XmlNode []解决方法?

  • 是唯一使用非通用集合支持的泛型集合的解决方案吗?

2 回答

  • 2

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

    DataContractSerializer在使用任何属性之前将使用ISerializable实现 . 对于 anyType 反序列化,它也没有解决方法 .

    这就是KnownTypeAttribute无法正常工作的原因 .

  • 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")]
    

相关问题