[英]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.