leejw51 / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
0 stars 0 forks source link

SkipConstructor does not do its job correctly in List items that support full reference tracking #203

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Please include an e-mail address if this might need a dialogue!
E-mail: foren@kevinstumpf.de
==============

What steps will reproduce the problem?
DataContracts:

    [ProtoContract(SkipConstructor = true)]
    public class SerializeClass
    {
        [ProtoMember(1, AsReference = true)]
        private SomeCollection _someList = null;
        public SomeCollection SomeList
        {
            get
            {
                return _someList;
            }
            set
            {
                _someList = value;
            }
        }
    }

    public class SomeCollection : List<SomeCollectionItem>
    {}

    [ProtoContract(SkipConstructor = true)]
    public class SomeCollectionItem
    {
        public SomeCollectionItem()
        {
            throw new InvalidOperationException("I should never be called");
        }

        public SomeCollectionItem(string init)
        {
            SomeField = init;
        }

        [ProtoMember(1)]
        public string SomeField;
    }

Serialization Code:
            SerializeClass m = new SerializeClass();

            var u = new SomeCollectionItem("ABC");
            m.SomeList = new SomeCollection();
            m.SomeList.Add(u);
            m.SomeList.Add(u);

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

            using(var reader = new StreamReader(OutputDir + "proto.bin"))
            {
                var deserialized = Serializer.Deserialize<SerializeClass>(reader.BaseStream);
                var areEqual = deserialized.SomeList[0] == deserialized.SomeList[1]; // has to be true
            }

What is the expected output? What do you see instead?
The constructor of SomeCollectionItem should not be called, no matter if the 
SomeList Property of SerializeClass is marked "AsReference" or not.

What version of the product are you using? On what operating system?
v2 beta 4 (r423). Windows 7 64 Bit.

Please provide any additional information below.
If you set AsReference=false on SomeList the constructor does not get called.
However, reference tracking is necessary as the collection can contain items 
that i serialize somewhere else in the whole graph.

Kevin

Original issue reported on code.google.com by kevinstu...@gmail.com on 11 Jul 2011 at 9:38

GoogleCodeExporter commented 9 years ago
Fixed in code, pending deployment

Original comment by marc.gravell on 12 Jul 2011 at 7:02

GoogleCodeExporter commented 9 years ago
Hi. This was supposedly fixed in r432 but I'm seeing a similar problem in r470. 
Example code:

[ProtoContract(SkipConstructor = true)]
    class B
    {
        public B()
        {
            Console.WriteLine("Constructor");
        }
    }

    [ProtoContract]
    class A
    {
        [ProtoMember(1)]
        public B b = new B();
    }

    class Program
    {
        private static byte[] Serialize(object obj)
        {
            var stream = new MemoryStream();
            Serializer.Serialize(stream, obj);
            return stream.ToArray();
        }

        private static T Deserialize<T>(byte[] serializedData)
        {
            var stream = new MemoryStream(serializedData);
            return Serializer.Deserialize<T>(stream);
        }

        public static void Main()
        {
            var data = Serialize(new A());
            Console.WriteLine("Calling deserialize");
            Deserialize<A>(data);
        }
    }

Output:

    Constructor
    Calling deserialize
    Constructor

Original comment by logix...@gmail.com on 2 Dec 2011 at 10:31