wcf 进行序列化时出错: info。

2025-05-20 14:55:43
推荐回答(1个)
回答1:

您没有对要序列化的内容加标识.或该变量的类型不属于可序列化类型范围内.

一、未知类型导致序列化失败

  .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, IEnumerable knownTypes);
 public DataContractSerializer(Type type, string rootName, string rootNamespace, IEnumerable knownTypes);
  public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace, IEnumerable knownTypes);
  public DataContractSerializer(Type type, IEnumerable knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);
  public DataContractSerializer(Type type, string rootName, string rootNamespace, IEnumerable knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);
  public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace, IEnumerable knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);
  
  public ReadOnlyCollection KnownTypes { get; }
}


为了方便后面的演示,使用的泛型服务方法Serialize为已知类型作相应的修正,通过第3个参数指定DataContractSerializer的已知类型列表。

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);
 }