5

私はこのクラスを持っています:

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 から継承するため、ISerializable を実装する必要があるため、保護されたコンストラクターと 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 であるため、テストは失敗します。(ただし、整数は正しく(逆)シリアル化されています)何が起こっているのですか?

編集:名前バッキングフィールドが非公開であることとは関係ありません。公開しても結果は同じです。

4

1 に答える 1

5

これは関係ありませんISerializableDataContractSerializer単に使用しません(使用 しますが、それをしたくありません...)ISerializableIXmlSerializable

XmlSerializerand (さらに言えば、データ バインディング)を含むほとんどのシリアライザーはDataContractSerializer、コレクションをエンティティとは異なるものとして扱います。どちらか一方の可能性がありますが、両方の可能性はありません。それが「コレクション」であることを検出するため、プロパティ (など)ではなく、コンテンツ(つまり、セット内にあるもの) をシリアル化します。Name

コレクションを継承するのではなく、カプセル化する必要があります。

また; を正しく使用するには、 /属性DataContractSerializerを追加するのが賢明です。例えば:[DataMember][DataContract]

[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;}
}
于 2009-08-16T19:31:26.620 に答える