如果我有以下课程,并尝试使用DataContractSerializer ConcreteClass
序列化.WriteObject(..)
个实例,我会收到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需要抽象基类来拥有无参数的构造函数呢? Here声明类型可以序列化,“具有一个没有参数的构造函数”,这对于ConcreteClass来说是正确的。我还为这个必需的构造函数添加了一些代码,我认为它不会在序列化过程中被调用。
完整的异常说:
System.Runtime.Serialization.InvalidDataContractException:Type 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);
}
}
}
答案 0 :(得分:-2)
您得到的异常是说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; }
}
如果我尝试序列化我的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; }
}
现在我们所拥有的将能够创建一个序列化文件。但是,没有任何信息,因为我们从未告诉我们DataContract要包含什么。为了解决这个问题,我们将DataMember属性添加到我们想要包含的类中的属性。
[DataContract]
public class Foo : Bar
{
[DataMember]
string one { get; set; }
string two { get; set; }
[DataMember]
string three { get; set; }
}
在序列化此类时添加了DataMember属性,它只会序列化有关字符串1和字符串3的信息。不包括字符串2,因为它没有专门用DataMember属性标记。