问题
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.
回答1:
This is nothing to do with ISerializable
; DataContractSerializer
simply doesn't use ISerializable
(it will use IXmlSerializable
, but you don't want to do that...)
Most serializers, including XmlSerializer
and DataContractSerializer
(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:
[Serializable, DataContract] // probably don't need [Serializable]
public class Group<T>
{
[DataMember]
public HashSet<T> Items { get; private set; }
protected Group()
{
Items = new HashSet<T>();
}
public Group(string name) : this()
{
Name = name;
}
[DataMember]
public string Name {get ;private set;}
}
来源:https://stackoverflow.com/questions/1285018/datacontractserializer-not-serializing-member-of-class-that-inherits-iserializab