您没有对要序列化的内容加标识.或该变量的类型不属于可序列化类型范围内.
一、未知类型导致序列化失败
.NET的类型可以分为两种:声明类型和真实类型。我们提倡面向接口的编程,对象的真实类型往往需要在运行时才能确定,在编程的时候往往只需要指明类型的声明类型,比如类型实现的接口或者抽象类。当我们使用基于接口或者抽象类创建的DataContractSerializer去序列化一个实现了该接口或者继承该抽象类的实例的时候,往往会因为对对象的真实类型无法识别造成不能正常地序列化。
namespace Artech.DataContractSerializerDemos
{
public interface IOrder
{
Guid ID
{ get; set; }
DateTime Date
{ get; set; }
string Customer
{ get; set; }
string ShipAddress
{ get; set; }
}
[DataContract]
public abstract class OrderBase : IOrder
{
[DataMember]
public Guid ID
{ get; set; }
[DataMember]
public DateTime Date
{ get; set; }
[DataMember]
public string Customer
{ get; set; }
[DataMember]
public string ShipAddress
{ get; set; }
}
[DataContract]
public class Order : OrderBase
{
[DataMember]
public double TotalPrice
{ get; set; }
}
}
通过下面的方式去序列化一个Order对象(注意泛型类型为IOrder或者OrderBase),将会抛出如图1所示SerializationException异常,提示Order类型无法识别
Order order = new Order()
{
ID = Guid.NewGuid(),
Customer = "NCS",
Date = DateTime.Today,
ShipAddress = "#328, Airport Rd, Industrial Park, Suzhou Jiangsu Province",
TotalPrice = 8888.88
};
Serialize(order, @"E:order.xml");
//或者
Serialize(order, @"E:order.xml");
二、DataContractSerializer的已知类型集合
解决上面这个问题的唯一途径就是让DataContractSerializer能够识别Order类型,成为DataContractSerializer的已知类型(Known Type)。DataContractSerializer内部具有一个已知类型的列表,只需要将Order的类型添加到这个列表中,就能从根本上解决这个问题。通过下面6个重载构造函数中的任意一个,均可以通过knownTypes参数指定DataContractSerializer的已知类型集合,该集合最终反映在DataContractSerializer的制度属性KnownTypes上。
public sealed class DataContractSerializer : XmlObjectSerializer
{
public DataContractSerializer(Type type, IEnumerableknownTypes);
public DataContractSerializer(Type type, string rootName, string rootNamespace, IEnumerableknownTypes);
public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace, IEnumerableknownTypes);
public DataContractSerializer(Type type, IEnumerableknownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);
public DataContractSerializer(Type type, string rootName, string rootNamespace, IEnumerableknownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);
public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace, IEnumerableknownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);
public ReadOnlyCollectionKnownTypes { get; }
}
为了方便后面的演示,使用的泛型服务方法Serialize
public static void Serialize(T instance, string fileName, IList konwnTypes)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T), konwnTypes, int.MaxValue, false, false, null);
using (XmlWriter writer = new XmlTextWriter(fileName, Encoding.UTF8))
{
serializer.WriteObject(writer, instance);
}
Process.Start(fileName);
}