我正在尝试在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模式的任何示例。
所以我的问题是:
答案 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无效的原因。