protobuf-net не сериализует свойства C # с частными установщиками

Я сегодня возился с 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


person aaronburro    schedule 25.09.2013    source источник


Ответы (2)


Это неявное поведение значения по умолчанию. Самое простое исправление - это, вероятно, пометить IsEmpty с IsRequired = true (в атрибуте свойства).

person Marc Gravell    schedule 25.09.2013

Нашел ответ здесь: c # protobuf-net при десериализации значение некоторого свойства всегда равно -1

В целях экономии места protobuf не сериализует значения по умолчанию для типов значений. В этом примере значение по умолчанию для .NET для bool равно false. Конструктор по умолчанию устанавливает для свойства IsEmpty значение true, и поскольку значение, которое я ожидаю, совпадает со значением по умолчанию .NET, protobuf пропускает сохранение этого значения, поэтому я получаю значение из конструктора по умолчанию.

Исправление заключается либо в установке IsRequired на TRUE, как говорит Марк, либо в использовании [ProtoContract(10), DefaultValue(true)] в параметре.

person aaronburro    schedule 25.09.2013