3

protobuf does not have built-in support of differentation between empty lists and null lists. However, our business objects do differ because null means that the list has not been pulled from the database yet whereas empty means no items found.

So I am trying to overcome this limitation using Surrogates in protobuf-net. The problem, however, is, that my surrogate does not get called at all.

Here is what I am doing:

//DataContracts
    [ProtoContract]
    public class SerializeClassCollectionContainer
    {
        [ProtoMember(1, AsReference=true)]
        public SerializeClassCollection Collection { get; set; }
    }

    [ProtoContract]
    public class SerializeClassCollection : List<SerializeClass>
    {
    }

[ProtoContract]
        public class SerializeClassCollectionSurrogate
        {
            [ProtoMember(1)]
            public bool IsEmpty { get; set; }

            [ProtoMember(2, AsReference = true)]
            public List<SerializeClass> Elements { get; set; }

            public static implicit operator SerializeClassCollection(SerializeClassCollectionSurrogate surrogate)
            {
                if (surrogate == null)
                    return null;

                if (surrogate.Elements != null)
                {
                    var col = new SerializeClassCollection();
                    col.AddRange(surrogate.Elements);
                    return col;
                }

                if (surrogate.IsEmpty)
                {
                    return new SerializeClassCollection();
                }

                return null;
            }

            public static implicit operator SerializeClassCollectionSurrogate(SerializeClassCollection collection)
            {
                if (collection == null)
                    return null;

                var surrogate = new SerializeClassCollectionSurrogate();
                surrogate.IsEmpty = collection.Count == 0;
                surrogate.Elements = collection.ToList();

                return surrogate;
            }
        }

//Evaluation
RuntimeTypeModel.Default[typeof(SerializeClassCollection)].SetSurrogate(typeof(Surrogates.SerializeClassCollectionSurrogate));

SerializeClassCollectionContainer serializeClassCollectionContainer = GetCustomObject();
            serializeClassCollectionContainer.Collection = new SerializeClassCollection(); //empty collection

            using (var writer = new StreamWriter(OutputDir + "proto.bin"))
            {
                Serializer.Serialize(writer.BaseStream, serializeClassCollectionContainer);
            }

            using(var reader = new StreamReader(OutputDir + "proto.bin"))
            {
                var deserialized = Serializer.Deserialize<SerializeClassCollectionContainer>(reader.BaseStream);
                if(deserialized.Collection == null)
                    throw new InvalidOperationException("Surrogate does not work");
            }

Am I doing something wrong? Or is this a feature and not supposed to work? Or is it supposed to work but a bug?

I tried this with revision 433 from the protobuf-net trunk.

Regards, TH

TwinHabit
  • 753
  • 8
  • 22
  • At current, lists are handled in a separate path that does not include surrogate handling. As such, you could say that `SetSurrogate` should probably throw. However, the scenario has merit. I think the best thing here is to log it as a feature request (or I can), and see how it fits in. Closing this, as I think it is a bit too localized. – Marc Gravell Jul 13 '11 at 07:30
  • Most serializers distinguish between _empty_ and _null_ collections. I understand, that protobuf is standarized protocol, and do not allow to it, but Marc - take a look at your implementation: you already added few modification, which brakes standard, but still works when using it on both ends of communication. Please take a look at similar question http://stackoverflow.com/questions/2378666/protobuf-net-serializing-an-empty-list – Bartosz Pierzchlewicz Oct 11 '11 at 12:53
  • @Marc what is the current status of lists with surrogate handling? what about other collection types (like arrays)? – Tamir Jun 30 '15 at 08:07

0 Answers0