DataContractSerializer Serialisierung nicht Mitglied der Klasse, die ISerializable erbt
-
18-09-2019 - |
Frage
Ich habe diese Klasse:
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; }
}
}
}
Wie aus HashSet erbt hat es ISerializable, daher den geschützten Konstruktor und GetObjectData Methode zu implementieren. Früher serialisiert I und deserialisiert diese Klasse erfolgreich mit dem BinaryFormatter.
Weil ich möchte, um die Ausgabe inspizieren können, die durch den Serializer generiert ich zum DataContractSerializer wechseln wollen.
Ich schrieb diesen 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);
}
Der Test schlägt fehl, weil die Name-Eigenschaft ist null! (Die ganzen Zahlen sind (de) serialisiert richtig obwohl) Was ist passiert?
EDIT: es hat nichts mit dem Namen dahinter liegenden Feld ist privat zu tun. es öffentlich zu machen hat das gleiche Ergebnis.
Lösung
Das ist nichts mit ISerializable
zu tun; DataContractSerializer
einfach nicht Verwendung ISerializable
(es IXmlSerializable
verwenden, aber Sie wollen nicht, das zu tun ...)
Die meisten Serializer, einschließlich XmlSerializer
und DataContractSerializer
(und Datenbindung, für diese Angelegenheit), treat Sammlungen als verschiedene Entitäten. Es kann ein oder die andere sein, aber nicht beides. Weil es erkennt, dass es sich um eine „Sammlung“ ist, es serialisiert die Inhalte (das heißt, was auch immer in der Menge enthalten ist), nicht die Eigenschaften (Name
usw.).
Sie sollten encapsulate eine Sammlung, anstatt inherit es.
Auch; richtig zu verwenden DataContractSerializer
, wäre es klug, die [DataMember]
/ [DataContract]
Attribute hinzuzufügen. Zum Beispiel:
[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;}
}