异常信息:
“System.Runtime.Serialization.SerializationException”类型的未经处理的异常在 System.Runtime.Serialization.dll 中发生
其他信息: 不应为数据协定名称为“Teacher:http://schemas.datacontract.org/2004/07/ConsoleApplication3”的类型“ConsoleApplication3.Teacher”。请考虑使用 DataContractResolver,或将任何未知类型以静态方式添加到已知类型的列表。例如,可以使用 KnownTypeAttribute 特性,或者将未知类型添加到传递给 DataContractSerializer 的已知类型列表。
想要序列化的对象:
1 public class Student : People 2 { 3 public Int32 Age { get; set; } 4 }
1 public abstract class People 2 { 3 public string Name { get; set; } 4 public string Address { get; set; } 5 }
序列化的方法:
1 public static string WriteJson<T>(T t) 2 { 3 using (MemoryStream ms = new MemoryStream()) 4 { 5 DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T)); 6 serializer.WriteObject(ms, t); 7 return Encoding.UTF8.GetString(ms.ToArray()); 8 } 9 }
方法调用:
1 People p = new Student() 2 { 3 Name = "小明", 4 Address = "章丘路110号", 5 Age = 14 6 }; 7 8 string jsonString = WriteJson<People>(p); 9 Console.WriteLine(jsonString);
然后就有了上面的异常
根据异常可以知道,虽然Student继承了People类,但是序列化的时候是People类型,也就是说序列化的时候并不知道 想要序列化的对象(Student类型),故产生了异常;根据异常提示,有两种解决方案:考虑使用 DataContractResolver,或将任何未知类型以静态方式添加到已知类型的列表。
经过了MSDN一番查询后,得到了两种可以序列化继承关系的对象的方法,
方式一,继承DataContractResolver类来实现:
1 public abstract class Animal 2 { 3 public string Name { get; set; } 4 } 5 6 public class Bird : Animal 7 { 8 public string Color { get; set; } 9 public Feather BDeather { get; set; } 10 } 11 12 public class Feather 13 { 14 public string Color { get; set; } 15 }
1 public static string WriteJson<T>(T t) 2 { 3 using (MemoryStream ms = new MemoryStream()) 4 { 5 Assembly assembly = Assembly.Load(new AssemblyName("ConsoleApplication3")); 6 DataContractSerializer serializer = new DataContractSerializer(typeof(T), null, Int32.MaxValue, false, true, null, new MyDataContractResolver(assembly)); 7 serializer.WriteObject(ms, t); 8 return Encoding.UTF8.GetString(ms.ToArray()); 9 } 10 }
1 Animal animal = new Bird() 2 { 3 Name = "鸭子", 4 Color = "白色", 5 BDeather = new Feather() { Color="纯白色"} 6 }; 7 string jsonString = WriteJson<Animal>(animal); 8 Console.WriteLine(jsonString);
1 public class MyDataContractResolver : DataContractResolver 2 { 3 4 private XmlDictionary dictionary = new XmlDictionary(); 5 Assembly assembly; 6 public MyDataContractResolver(Assembly assembly) 7 { 8 this.assembly = assembly; 9 } 10 public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver) 11 { 12 Type type = knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, knownTypeResolver); 13 if (type == null) 14 { 15 type = Type.GetType(typeName + ", " + typeNamespace); 16 } 17 return type; 18 } 19 20 public override bool TryResolveType(Type type, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace) 21 { 22 knownTypeResolver.TryResolveType(type, declaredType, knownTypeResolver, out typeName, out typeNamespace); 23 if (typeName == null || typeNamespace == null) 24 { 25 XmlDictionary dictionary = new XmlDictionary(); 26 typeName = dictionary.Add(type.FullName); 27 typeNamespace = dictionary.Add(type.Assembly.FullName); 28 } 29 return true; 30 } 31 }
输出结果:
方式二,通过KnownTypeAttribute添加识别类型:
1 [KnownType(typeof(Student))] 2 [KnownType(typeof(Teacher))] 3 [KnownType(typeof(Pupil))] 4 [DataContract] 5 public abstract class People 6 { 7 [DataMember] 8 public string Name { get; set; } 9 [DataMember] 10 public string Address { get; set; } 11 }
1 public class Student : People 2 { 3 4 public Int32 Age { get; set; } 5 } 6 7 public class Pupil : Student 8 { 9 10 }
1 public class Teacher : People 2 { 3 public Course T_course { get; set; } 4 } 5 6 public class Course 7 { 8 public string Name { get; set; } 9 public int Times { get; set; } 10 }
输出结果:
关于更详细的描述,请参考以下MSDN的内容:
http://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.knowntypeattribute.aspx
http://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.datacontractserializer%28v=vs.110%29.aspx