DataContractSerializer 未序列化继承 ISerialized 的类的成员
我有这个类:
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Grouping
{
[Serializable]
public class Group<T> : HashSet<T>
{
public Group(string name)
{
this.name = name;
}
protected Group(){}
protected Group(SerializationInfo info, StreamingContext context):base(info,context)
{
name = info.GetString("koosnaampje");
}
public override void GetObjectData(SerializationInfo info,StreamingContext context)
{
base.GetObjectData(info,context);
info.AddValue("koosnaampje", Name);
}
private string name;
public string Name
{
get { return name; }
private set { name = value; }
}
}
}
由于它继承自 HashSet,因此它必须实现 ISerialized,因此需要实现受保护的构造函数和 GetObjectData 方法。 以前我用 BinaryFormatter 成功地序列化和反序列化了这个类。
因为我希望能够检查序列化器生成的输出,所以我想切换到 DataContractSerializer。
我编写了这个测试:
[TestMethod]
public void SerializeTest()
{
var group = new Group<int>("ints"){1,2,3};
var serializer = new DataContractSerializer(typeof (Group<int>));
using (var stream=File.OpenWrite("group1.xml"))
{
serializer.WriteObject(stream,group);
}
using (var stream=File.OpenRead("group1.xml"))
{
group = serializer.ReadObject(stream) as Group<int>;
}
Assert.IsTrue(group.Contains(1));
Assert.AreEqual("ints",group.Name);
}
测试失败,因为 Name 属性为 null! (尽管整数被正确地(反)序列化了) 怎么了?
编辑:它与名称支持字段是私有的无关。公开也有同样的结果。
I have this class:
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Grouping
{
[Serializable]
public class Group<T> : HashSet<T>
{
public Group(string name)
{
this.name = name;
}
protected Group(){}
protected Group(SerializationInfo info, StreamingContext context):base(info,context)
{
name = info.GetString("koosnaampje");
}
public override void GetObjectData(SerializationInfo info,StreamingContext context)
{
base.GetObjectData(info,context);
info.AddValue("koosnaampje", Name);
}
private string name;
public string Name
{
get { return name; }
private set { name = value; }
}
}
}
As it inherits from HashSet it has to implement ISerializable, hence the protected constructor and GetObjectData method.
Formerly I serialized and deserialized this class succesfully with the BinaryFormatter.
Because I want to be able to inspect the output that is generated by the serializer I want to switch to the DataContractSerializer.
I wrote this test:
[TestMethod]
public void SerializeTest()
{
var group = new Group<int>("ints"){1,2,3};
var serializer = new DataContractSerializer(typeof (Group<int>));
using (var stream=File.OpenWrite("group1.xml"))
{
serializer.WriteObject(stream,group);
}
using (var stream=File.OpenRead("group1.xml"))
{
group = serializer.ReadObject(stream) as Group<int>;
}
Assert.IsTrue(group.Contains(1));
Assert.AreEqual("ints",group.Name);
}
The test fails because the Name property is null! (the integers are (de)serialized correctly though)
What is happening?
EDIT: it has nothing to do with the name backing field being private. Making it public has the same result.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这与
ISerialized
无关;DataContractSerializer
根本不使用ISerialized
(它将使用IXmlSerialized
,但您不想这样做...)大多数序列化程序,包括 XmlSerializer 和 DataContractSerializer(以及数据绑定),都将集合视为与实体不同的方式。它可以是或其中之一,但不能同时是两者。因为它检测到它是一个“集合”,所以它序列化内容(即集合中的任何内容),而不是属性(
名称
等)。您应该封装一个集合,而不是继承它。
还;要正确使用
DataContractSerializer
,明智的做法是添加[DataMember]
/[DataContract]
属性。例如:This is nothing to do with
ISerializable
;DataContractSerializer
simply doesn't useISerializable
(it will useIXmlSerializable
, but you don't want to do that...)Most serializers, including
XmlSerializer
andDataContractSerializer
(and data-binding, for that matter), treat collections as different to entities. It can be one or the other, but not both. Because it detects that it is a "collection", it serializes the contents (i.e. whatever is in the set), not the properties (Name
etc).You should encapsulate a collection, rather than inherit it.
Also; to correctly use
DataContractSerializer
, it would be wise to add the[DataMember]
/[DataContract]
attributes. For example: