簡體   English   中英

DataContractSerializer 需要抽象基礎 class 中的無參數構造函數

[英]DataContractSerializer requires parameterless constructor in abstract base class

當我有以下類並嘗試使用DataContractSerializer .WriteObject(..)序列化ConcreteClass實例時,我得到一個InvalidDataContractException

public abstract class AbstractClass
{            
  protected AbstractClass(string text) { }
}

public class ConcreteClass : AbstractClass
{
  public ConcreteClass() : base("text") {  } 
}

序列化new DataContractSerializer(typeof(ConcreteClass)實例化。

使用XmlSerializer沒有問題。

現在添加public AbstractClass() {}

兩個序列化程序都可以工作。

那么為什么 DataContractSerializer 要求抽象基類有一個無參數的構造器呢? 這里指出,可以序列化類型“具有沒有參數的構造函數”,這對於 ConcreteClass 是正確的。 我還向這個必需的構造函數添加了一些代碼,我不認為它在序列化過程中被調用過。


完整的例外說:

System.Runtime.Serialization.InvalidDataContractException:無法序列化類型 AbstractClass'。 考慮使用 DataContractAttribute 屬性對其進行標記,並使用 DataMemberAttribute 屬性標記您想要序列化的所有成員。 有關其他支持的類型,請參閱 Microsoft .NET 框架文檔。

如果我離開無參數構造函數而是使用建議的屬性,它甚至可以工作。 那么為什么會有區別以及為什么要嘗試序列化抽象 class? 當然,抽象 class 中可能有屬性之類的東西,但它們不應該與 ConcreteClass 實例(繼承這些東西)一起序列化嗎?

編輯

我的確切代碼:

namespace SerilizationTest
{
  public abstract class AbstractClass
  {
    public string StringProperty { get; set; }

    //This constructor is required (although never called).
    //If not present we get "InvalidDataContractException :
    //Type AbstractClass cannot be serialized"
    public AbstractClass()
    {
      Console.WriteLine("We won't see this.");
    }

    public AbstractClass(string text)
    {
      StringProperty = text;
    }
  }

  public class ConcreteClass : AbstractClass
  {
    public ConcreteClass() : base("text") { }
  }

  class Program
  {
    static void Main()
    {
      var serializer = new DataContractSerializer(typeof(ConcreteClass));
      var memStream = new MemoryStream();
      serializer.WriteObject(memStream, new ConcreteClass());
      memStream.Seek(0, SeekOrigin.Begin);
      var deserializedObj = (ConcreteClass)serializer.ReadObject(memStream);
      Console.WriteLine(deserializedObj.StringProperty);
    }
  }
}

您得到的異常是說 AbstractClass 上沒有 [DataContract] 屬性。

DataContract 是一個屬性,用於標記可序列化的類。 如果您通過使用 DataMember 屬性告訴它這樣做,則此屬性將僅包含要序列化的 class 中的屬性。

DataMember 屬性用於標記您想要在可序列化 class 中使用哪些屬性。

此屬性位於 System.Runtime.Serialization;

例如...

public abstract class Bar
{
}

public class Foo : Bar
{
    string one { get; set; }
    string two { get; set; }
    string three { get; set; }
}

如果我嘗試序列化我的 Foo class 那么我會得到你的例外。 因此,如果我將 DataContract 屬性添加到我的 Bar class 中,就像異常表明下次我嘗試序列化時一樣,我將得到相同的錯誤,只是指向我的代碼的另一部分,即 Foo class 本身。 我需要做的是像這樣將 DataContract 添加到兩者中。

[DataContract]
public abstract class Bar
{
}

[DataContract]
public class Foo : Bar
{
    string one { get; set; }
    string two { get; set; }
    string three { get; set; }
}

所以現在我們所擁有的將能夠創建一個序列化文件。 但是,不會有任何信息,因為我們從未告訴我們的 DataContract 要包含什么。為了解決這個問題,我們將 DataMember 屬性添加到我們想要包含的 class 中的屬性中。

[DataContract]
public class Foo : Bar
{
    [DataMember]
    string one { get; set; }
    string two { get; set; }
    [DataMember]
    string three { get; set; }
}

在序列化此 class 時添加 DataMember 屬性,它將僅序列化有關字符串 1 和字符串 3 的信息。 字符串 2 將不包括在內,因為它沒有專門用 DataMember 屬性標記。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM