1

我有两个简单的类,我想用 protobuf-net 序列化它们。一切看起来都不错,但是当我反序列化 Body 属性时为空。知道我做错了什么吗?

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using ProtoBuf;

namespace Protobuf_test
{
    public class Program
    {
        private static void Main(string[] args)
        {
            var innerObject = new Inner() { Id = Guid.NewGuid() };
            var outerObject = new Outer() { Body = innerObject };

            using (var stream = File.Create("serialized.bin"))
            {
                Serializer.Serialize(stream, outerObject);
            }
            using (var file = File.OpenRead("serialized.bin"))
            {
                var deserialized = Serializer.Deserialize<Outer>(file);
            }
        }
    }

    [DataContract]
    public class Inner
    {
        [DataMember]
        public Guid Id { get; set; }
    }

    [DataContract]
    public class Outer
    {
        [DataMember]
        public object Body { get; set; }
    }
}
4

2 回答 2

1

两个问题:

  1. protobuf-net 要求每个成员有一个正整数密钥;这可以通过Order=on提供[DataMember]。数字越小越好,所以通常这意味着1, 2, 3...

  2. protobuf 规范是一个模式绑定的序列化器;它想提前了解数据;object不能很好地工作。

但这会起作用:

[DataContract]
public class Inner
{
    [DataMember(Order=1)]
    public Guid Id { get; set; }
}

[DataContract]
public class Outer
{
    [DataMember(Order=1)]
    public Inner Body { get; set; }
}

对灵活类型的数据(即)有一些支持object,但请注意,它是 protobuf-net 特定的(它不会很好地实现可移植性)。我鼓励您先查看类型化方法。但它可以做到这一点:如果你不这样做,我会更喜欢它;p

如果您无法更改现有模型,那么我建议的第一件事是:添加一个单独的 DTO 模型,该模型看起来很像您的现有模型,但标记为序列化,并使用它 - 并在两个模型之间添加垫片。如果不是一个选项,您需要将系统配置为 a: 为成员定义键,然后 b: 告诉它使用dynamic。例如:

var config = RuntimeTypeModel.Default;
config.Add(typeof(Inner),false).Add("Id");
config.Add(typeof(Outer), false).AddField(1, "Body").DynamicType = true;

(注意:Serializer.*基本上是一个捷径RuntimeTypeModel.Default.*,所以这个配置确实与方法有关Serializer.*

于 2013-01-10T13:26:04.847 回答
0

对于对象属性,您可以使用:

[ProtoMember(1, DynamicType=true)] 公共对象值 { 获取;放; }

于 2013-10-24T20:04:15.130 回答