【问题标题】:How to Serialize Inherited Class with ProtoBuf-Net如何使用 ProtoBuf-Net 序列化继承的类
【发布时间】:2012-10-10 22:28:44
【问题描述】:

如果这是重复的,我很抱歉。我已经在几个地方搜索了我可能理解的答案,包括:

ProtoBuf.net Base class properties is not included when serializing derived class

Serialize inherited classes using protobuf-net

我很抱歉,但我并没有真正理解答案。我正在寻找一个更快更紧凑的二进制序列化程序,而 ProtoBuf 看起来可能是答案。我需要序列化一组都派生自一个基类的类。它们有很多,所以在提交编辑类代码之前,我运行了一个简单的测试。此外,我不想以任何可能影响反序列化使用 NET 二进制序列化程序生成的旧持久文件的方式修改类。

这是基类:

[ProtoContract]
    public class BaseClass
    {
        [ProtoMember(1)]
        public string Name
        {
            get; set;
        }
        [ProtoMember(2)]
        public int Age
        {
            get; set;
        }
    }

这是派生类:

[ProtoContract]
    public class SubClass1 : BaseClass
    {
        [ProtoMember(3)]
        public string Town
        {
            get; set;
        }

        [ProtoMember(4)]
        public Sex Sex
        {
            get; set;
        }
    }

这是序列化和反序列化的代码(直接取自入门指南

var person = new SubClass1 { Age = 25, Name = "Fred", Town = "Denbigh", Sex = Sex.Female };

            using (var file = File.Create(filename))
            {
                Serializer.Serialize(file, person);
            }

和反序列化:

SubClass1 newPerson;
            using (var file = File.OpenRead(filename))
            {
                newPerson = Serializer.Deserialize<SubClass1>(file);
            }

            MessageBox.Show(newPerson.Name + 
                " : " + newPerson.Town + 
                " : " + newPerson.Age.ToString() + 
                " : " + newPerson.Sex);

结果是“:Denbigh:0:女性”

不知何故,基类属性中的值没有被序列化?我最初使用派生类的 ProtoMember 索引作为 1、2 对其进行了测试。我有点认为这行不通,所以选择了 3、4。似乎没有什么区别。在我的妄想症中,我使用标准 NET 二进制序列化程序运行了相同的测试并得到了预期的结果:“Fred : Denbigh : 25 : Female”

请问我错过了什么?

【问题讨论】:

    标签: c# serialization protobuf-net


    【解决方案1】:

    您需要在基类上使用ProtoInclude 属性:

    [ProtoContract]
    [ProtoInclude(500, typeof(SubClass1 ))]
    public class BaseClass
    {
    

    id arg(上例中为 500)对于该类应该是唯一的。更多信息见this文章

    【讨论】:

    • 非常感谢 - 这么简单
    • @RenniePet 它是我的网站,因维护而停机,时机不对!
    • @wal 500 id arg 对于子类或解决方案中的所有 ProtoInclude 属性应该是唯一的?我相信它是第一个,但你让它听起来像它的第二个
    • 这个的设计好像倒退了。如果我有一个位于另一个库中的基类不(也不应该)知道我的应用程序中的类怎么办?可以把标签号加到子类里吗?
    • @rushonerok 我还应该注意:使用 protobuf-net v2,您可以即时构建序列化程序,这意味着您不必使用属性 装饰类,请参阅我的文章 @987654322 @我在应用程序中使用此方法来处理您描述的情况-即我定义了一个序列化模型,该模型知道(引用)我的应用程序中需要序列化的所有类-这意味着您的基类可以保持对任何子类的无知和还在序列化!
    【解决方案2】:

    我知道它已经很老了,但可能会对某人有所帮助。在某些情况下,您可以通过在子类型中重新定义基本属性来解决此问题:

    [ProtoContract]
    public class SubClass1 : BaseClass
    {
        [ProtoMember(1)]
        public string BaseName
        {
            get{return base.Name;}
            set{base.Name = value;}
        }
    
        ...
    
        [ProtoMember(3)]
        public string Town
        {
            get; set;
        }
    
        [ProtoMember(4)]
        public Sex Sex
        {
            get; set;
        }
    }
    

    【讨论】:

    • 我认为这行不通,因为SubClass1 将有两个属性定义为ProtoMember,索引=1(NameBaseName
    猜你喜欢
    • 2012-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多