下面的程序试图对一个层次结构中的泛型类型对象进行序列化和反序列化,但是会出现下面代码后面列出的错误。
该怎么做才能让它正常工作呢?
代码:
[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',命名空间为的'Element'。
确实,在上面的主方法中,xml
就是这个(已添加空格):
<DerivedAOfstring
xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication7"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Foo>foo</Foo>
</DerivedAOfstring>
我意识到我必须让序列化程序了解我的类型层次结构,但是我已经尝试了上面列表中KnownType
属性的许多不同变体,但都没有成功。正确的方法是什么?