代码之家  ›  专栏  ›  技术社区  ›  Dabblernl

DataContractSerializer未序列化继承ISerializable的类的成员

  •  5
  • Dabblernl  · 技术社区  · 16 年前

    我有这门课:

    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; }
            }
        }
    }
    

    由于它继承自哈希集,因此必须实现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属性为空!(整数被(反)序列化) 发生什么事了?

    编辑:这与名称支持字段是私有的无关。把它公之于众也有同样的结果。

    1 回复  |  直到 14 年前
        1
  •  5
  •   Marc Gravell    16 年前

    这与 ISerializable ; DataContractSerializer 根本不 使用 可分割的 (它将使用 IXmlSerializable ,但你不想这样做…)

    大多数序列化程序,包括 XmlSerializer 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;}
    }
    
    推荐文章