0

I am getting the following error message when trying to serialize my object graph:

Possible recursion detected (offset: 4 level(s)): TestProtobufSerialization.Program+SI

My model looks like this:

    [ProtoContract(ImplicitFields = ImplicitFields.AllPublic, AsReferenceDefault = true)]
    [ProtoInclude(101, typeof(ST))]
    [ProtoInclude(102, typeof(SI))]
    public class Base 
    {
        public string CreateBy { get; set; }
        public string ModifiedBy { get; set; }
    }

    [ProtoContract(ImplicitFields = ImplicitFields.AllPublic, AsReferenceDefault = true)]
    public class ST : Base
    {
        public string Id { get; set; }
        public List<SI> Indexes { get; set; }
    }

    [ProtoContract(ImplicitFields = ImplicitFields.AllPublic, AsReferenceDefault = true)]
    public class SI : Base
    {
        public string Id { get; set; }
        public ST ST { get; set; }
    }

The actual code to serialize is the following:

        var st = new ST() { Id = "ST001" };
        var si = new SI() { Id = "SI001" };

        st.Indexes = new List<SI>();
        st.Indexes.Add(si);
        si.ST = st;


        ST newST = serializeDeserializeWithProto<ST>(st, "testing_cyclic_references");

        Debug.Assert(st != null, "ST is null!");

and the helper method is:

    private static T serializeDeserializeWithProto<T>(T input, string fileName)
    {
        using (var file = File.Create(fileName + ".bin"))
        {
            Serializer.Serialize(file, input);
        }

        T output;
        using (var file = File.OpenRead(fileName + ".bin"))
        {
            output = Serializer.Deserialize<T>(file);
        }

        string proto = Serializer.GetProto<T>();
        File.WriteAllText(typeof(T).ToString() + "_proto.txt", proto, Encoding.ASCII);

        Console.WriteLine(proto);

        return output;
    }

When I am trying to run this code I get the above mentioned exception. The interesting thing is that if I remove the Base class from the ST and SI classes the serialization works. I would like to understand why the serialization works without the Base class and it does not work with the Base class being the parent of ST and SI.

I also created a gist for my repro code.

gyurisc
  • 11,234
  • 16
  • 68
  • 102
  • 1
    But you have a cycle either way, right? – helb Aug 21 '15 at 09:06
  • 1
    possible duplicate of [protobuf-net: Possible recursion detected](http://stackoverflow.com/questions/10070710/protobuf-net-possible-recursion-detected) – James Aug 21 '15 at 09:11
  • @JamesBarrass I would argue that is duplicate of the question you link to. I am looking for an answer as to why removing the Base class from my model classes solves the cyclic reference problem. I spent couple of hours to track down the issue in my code and then simplify the problem enough, so I can present it here. I might need to rephrase the title and my question, so it will not seem like a duplicate. – gyurisc Aug 22 '15 at 12:35
  • @helb yes, I always have a cycle, but when the base class is not the parent of ST and SI I do not get an exception. – gyurisc Aug 22 '15 at 12:36

1 Answers1

0

I think I found an answer. When changing how the repeated properties are declared in ST type, I have no more exceptions:

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic, AsReferenceDefault = true)]
public class ST : Base
{
    public string Id { get; set; }

    [ProtoMember(401, AsReference = true)]
    public List<SI> Indexes { get; set; }
}

I still do not understand why I need to add an extra attribute to the collection properties when I declared that I want all public properties to be serialized as reference. I posted a follow up question to find this out:

Difference between how ProtoContract AsReference works when applied on a repeated property compared to a normal property

Community
  • 1
  • 1
gyurisc
  • 11,234
  • 16
  • 68
  • 102