从我的对象图中删除父 class 时,不再抛出 Protobuf-net 递归异常
Protobuf-net recursion exception is not thrown anymore, when removing the parent class from my object graph
我在尝试序列化我的对象图时收到以下错误消息:
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 classes 中删除 Base class,序列化就会起作用。我想了解为什么序列化在没有 Base class 的情况下工作并且它不适用于 Base class 作为 ST 和 SI 的父级。
我还创建了一个 gist for my repro 代码。
我想我找到了答案。当更改重复属性在 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; }
}
我仍然不明白为什么在声明我希望将所有 public 属性序列化为引用时,我需要向集合属性添加一个额外的属性。我发布了一个后续问题来找出答案:
Difference between how ProtoContract AsReference works when applied on a repeated property compared to a normal property
我在尝试序列化我的对象图时收到以下错误消息:
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 classes 中删除 Base class,序列化就会起作用。我想了解为什么序列化在没有 Base class 的情况下工作并且它不适用于 Base class 作为 ST 和 SI 的父级。
我还创建了一个 gist for my repro 代码。
我想我找到了答案。当更改重复属性在 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; }
}
我仍然不明白为什么在声明我希望将所有 public 属性序列化为引用时,我需要向集合属性添加一个额外的属性。我发布了一个后续问题来找出答案:
Difference between how ProtoContract AsReference works when applied on a repeated property compared to a normal property