protobuf-net 不使用私有设置器序列化 C# 属性

Posted

技术标签:

【中文标题】protobuf-net 不使用私有设置器序列化 C# 属性【英文标题】:protobuf-net not serializing C# properties with private setters 【发布时间】:2013-09-25 21:46:15 【问题描述】:

我今天一直在捣鼓 protobuf-net,遇到了一个奇怪的情况。下面的代码没有按预期反序列化。最后两次反序列化尝试成功,但不正确。反序列化对象的 IsEmpty 设置为 true,而实际上它应该设置为 false。我已经能够使用私有设置器获取属性以进行序列化就好了,但是这个行为不正确。跟链式默认构造函数有关系吗?

class Program2

    static void Main(string[] args)
    
        var comp = new FooComparer();

        // this deserializes fine.  woot!
        using (var ms = new MemoryStream())
        
            Console.WriteLine("Serializing an empty Foo");
            var args1 = new Foo();
            Serializer.Serialize(ms, args1);
            ms.Position = 0;
            var result = Serializer.Deserialize(ms);
            Console.WriteLine("Serialization successful: 0", comp.Equals(args1, result));
            Console.WriteLine();
        

        // this deserializes incorrectly
        using (var ms = new MemoryStream())
        
            Console.WriteLine("Serializing a Foo with just a string");
            var args1 = new Foo("576000BJ1");
            Serializer.Serialize(ms, args1);
            ms.Position = 0;
            var result = Serializer.Deserialize(ms);
            Console.WriteLine("Serialization successful: 0", comp.Equals(args1, result));
            Console.WriteLine();
        

        // this deserializes incorrectly
        using (var ms = new MemoryStream())
        
            Console.WriteLine("Serializing a Foo with an int");
            var args1 = new Foo(42);
            Serializer.Serialize(ms, args1);
            ms.Position = 0;
            var result = Serializer.Deserialize(ms);
            Console.WriteLine("Serialization successful: 0", comp.Equals(args1, result));
            Console.WriteLine();
        

        Console.WriteLine("Got dat 190% serialization");
    


[ProtoContract]
class Foo

    private Foo(bool isEmpty, string fooString, int? fooInt)
    
        this.IsEmpty = isEmpty;
        this.FooString = fooString;
        this.FooInt = fooInt;
    

    public Foo() : this(true, null, null)  
    public Foo(string foo) : this(false, foo, null)  
    public Foo(int foo) : this(false, null, foo)  

    [ProtoMember(10)] public bool IsEmpty  get; private set; 
    [ProtoMember(20)] public string FooString  get; private set; 
    [ProtoMember(30)] public int? FooInt  get; private set; 


class FooComparer : IEqualityComparer

    public bool Equals(Foo x, Foo y)
    
        return (x == null && y == null) ||
                (x != null && y != null &&
                x.IsEmpty == y.IsEmpty &&
                String.Equals(x.FooString, y.FooString, StringComparison.Ordinal) &&
                x.FooInt == y.FooInt);
    

    public int GetHashCode(Foo obj)  return 1;    // don't care about this

编辑: 我正在使用 .NET 3.5 和 protobuf 2.0.0.666

【问题讨论】:

【参考方案1】:

这是隐含的默认值行为。最简单的解决方法可能是将 IsEmpty 标记为 IsRequired=true(在属性属性上)。

【讨论】:

【参考方案2】:

在这里找到答案:c# protobuf-net when deserialize the some property value always is -1

为了节省空间,protobuf 不会序列化值类型的默认值。 在此示例中,bool 的 .NET 默认值为 false。默认构造函数将IsEmpty 属性设置为true,并且由于我期望它具有的值与.NET 默认值相同,protobuf 跳过保存该值,因此我从默认构造函数中获取值。

修复方法是将 IsRequired 设置为 TRUE,就像 Marc 所说的那样,或者在参数上使用 [ProtoContract(10), DefaultValue(true)]

【讨论】:

以上是关于protobuf-net 不使用私有设置器序列化 C# 属性的主要内容,如果未能解决你的问题,请参考以下文章

使用 protobuf-net 为 Windows 商店应用程序序列化私有成员

Protobuf-net / NetCore2:反序列化忽略带注释的私有字段

protobuf-net 使用啥基本序列化器来输出字节数组?

为啥我的代码中的 protobuf-net 反序列化器比流式读取 csv 慢得多

使用带有 protobuf-net 异常的代理对 List<T> 进行序列化

使用 ProtoBuf-net 反序列化派生类型(字典)未正确设置对象字段