use*_*754 5 c# serialization constructor abstract-class datacontractserializer
当我具有以下类并且尝试ConcreteClass使用DataContractSerializer序列化实例时,.WriteObject(..)我得到了一个InvalidDataContractException。
public abstract class AbstractClass
{
protected AbstractClass(string text) { }
}
public class ConcreteClass : AbstractClass
{
public ConcreteClass() : base("text") { }
}
Run Code Online (Sandbox Code Playgroud)
序列化器用实例化new DataContractSerializer(typeof(ConcreteClass)。
使用XmlSerializer没问题。
现在,当添加 public AbstractClass() {}
两个序列化器都可以工作。
那么,为什么DataContractSerializer要求抽象基类具有无参数构造函数?这里说明可以对类型进行序列化,即“具有不带参数的构造函数”,这对于ConcreteClass是正确的。我还向此必需的构造函数中添加了一些代码,而且我认为在序列化过程中从未调用过它。
完整的异常显示:
System.Runtime.Serialization.InvalidDataContractException:类型AbstractClass'不能序列化。考虑使用DataContractAttribute属性标记它,并使用DataMemberAttribute属性标记要序列化的所有成员。有关其他受支持的类型,请参见Microsoft .NET Framework文档。
如果我离开无参数构造函数,而是使用建议的属性,它甚至可以工作。那么为什么会有区别,为什么要尝试对抽象类进行序列化呢?当然,抽象类中可能有诸如属性之类的东西,但是否不应该将它们与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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 -3
您得到的异常是,AbstractClass 上没有 [DataContract] 属性。
DataContract 是一个属性,用于标记可序列化的类。如果您使用 DataMember 属性告诉它这样做,则该属性只会包含要序列化的类中的属性。
DataMember 属性用于标记可序列化类中需要哪些属性。
该属性可在 System.Runtime.Serialization 中找到;
例如...
public abstract class Bar
{
}
public class Foo : Bar
{
string one { get; set; }
string two { get; set; }
string three { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试序列化我的 Foo 类,那么我会得到你的例外。因此,如果我将 DataContract 属性添加到 Bar 类中,就像异常所暗示的那样,下次我尝试序列化时,我将得到相同的错误,只是指向代码的另一部分,即 Foo 类本身。我需要做的就是像这样将 DataContract 添加到两者中。
[DataContract]
public abstract class Bar
{
}
[DataContract]
public class Foo : Bar
{
string one { get; set; }
string two { get; set; }
string three { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在我们已经能够创建序列化文件了。但是,不会有任何信息,因为我们从未告诉 DataContract 要包含哪些内容。为了解决此问题,我们将 DataMember 属性添加到我们想要包含的类中的属性中。
[DataContract]
public class Foo : Bar
{
[DataMember]
string one { get; set; }
string two { get; set; }
[DataMember]
string three { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
通过在序列化此类时添加 DataMember 属性,它将仅序列化有关字符串一和字符串三的信息。字符串二不会被包含,因为它没有专门用 DataMember 属性标记。