【发布时间】:2016-09-14 00:38:32
【问题描述】:
以下程序尝试从层次结构中序列化然后反序列化泛型类型的对象,但失败并出现代码下方列出的错误。
如何让它发挥作用?
代码:
[DataContract]
[KnownType(nameof(GetKnownTypes))]
public abstract class Base<T>
{
private static Type[] GetKnownTypes()
{
return new[] {typeof(DerivedA<T>)};
}
}
[DataContract]
public class DerivedA<T> : Base<T>
{
[DataMember]
public T Foo { get; set; }
}
class Program
{
private static void Main()
{
// This works fine
var foo = new DerivedA<string> { Foo = "foo" };
var xml = Serialize(foo);
var foo2 = Deserialize<DerivedA<string>>(xml);
Console.WriteLine(foo2.Foo); // foo
// This throws the exception below
// (from serializer.ReadObject() in the Deserialize method)
var foo3 = Deserialize<Base<string>>(xml);
}
private static string Serialize<T>(T o)
{
string result = null;
var serializer = new DataContractSerializer(o.GetType());
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, o);
stream.Position = 0;
var reader = new StreamReader(stream);
result = reader.ReadToEnd();
}
return result;
}
private static T Deserialize<T>(string xml)
{
var result = default(T);
var serializer = new DataContractSerializer(typeof(T));
using (var stream = new MemoryStream())
{
var writer = new StreamWriter(stream);
writer.Write(xml);
writer.Flush();
stream.Position = 0;
result = (T)serializer.ReadObject(stream);
}
return result;
}
}
例外情况:
Unhandled Exception: System.Runtime.Serialization.SerializationException: Error in line 1 position 139. Expecting element 'BaseOfstring' from namespace 'http://schemas.datacontract.org/2004/07/ConsoleApplication7'.. Encountered 'Element' with name 'DerivedAOfstring', namespace 'http://schemas.datacontract.org/2004/07/ConsoleApplication7'.
at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlDictionaryReader reader)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(Stream stream)
at ConsoleApplication7.Program.Deserialize[T](String xml) in c:\users\tly01\documents\visual studio 2015\Projects\ConsoleApplication7\ConsoleApplication7\Program.cs:line 65
消息中最有趣的部分很清楚出了什么问题:
期待来自命名空间的元素“BaseOfstring”。遇到名称为“DerivedAOfstring”、命名空间的“元素”。
果然,上面main方法中的xml就是这个(加了空格):
<DerivedAOfstring
xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication7"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Foo>foo</Foo>
</DerivedAOfstring>
我意识到我必须以某种方式让序列化程序知道我的类型层次结构,但我已经尝试了上面列表中KnownType 属性的许多不同变体,但没有一个是富有成果的。完成这项工作的正确方法是什么?
【问题讨论】:
标签: c# generics inheritance serialization datacontractserializer