当从我的对象图中删除父类时,不再抛出Protobuf-net递归异常

本文关键字:不再 Protobuf-net 异常 递归 我的 对象图 父类 删除 | 更新日期: 2023-09-27 18:09:15

当尝试序列化我的对象图时,我得到以下错误消息:

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

我的模型是这样的:

    [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; }
    }

要序列化的实际代码如下:

        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!");

和辅助方法是:

    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;
    }

当我试图运行这段代码时,我得到了上面提到的异常。有趣的是,如果我从ST和SI类中删除基类,序列化就会起作用。我想了解为什么序列化在没有基类的情况下工作,并且基类是ST和SI的父类时不起作用。

我还为我的repro代码创建了一个要点。

当从我的对象图中删除父类时,不再抛出Protobuf-net递归异常

我想我找到答案了。当更改ST类型中重复属性的声明方式时,我没有更多的异常:

[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; }
}

我仍然不明白,当我声明要将所有公共属性序列化为引用时,为什么需要向集合属性添加一个额外的属性。我发布了一个后续问题来找出这个问题:

ProtoContract AsReference应用于重复属性与普通属性的区别