ProtoBuf-net AsReference需要Activator.CreateInstance中的公共构造函数吗?

在我的两个类中工作时看起来像这样(最小)

using System; using System.Collections.Generic; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using System.IO; using ProtoBuf; namespace Sandbox { public partial class Form1 : Form { public Form1() { Family family = new Family(); Child child1 = new Child(1); Child child2 = new Child(2); Parent parent = new Parent(new List() { child1, child2 }); family.Add(parent); string file = "sandbox.txt"; try { File.Delete(file); } catch { } using (var fs = File.OpenWrite(file)) { Serializer.Serialize(fs, family); } using (var fs = File.OpenRead(file)) { family = Serializer.Deserialize(fs); } System.Diagnostics.Debug.Assert(family != null, "1. Expect family not null, but not the case."); } } [ProtoContract()] public class Child { [ProtoMember(1, AsReference = true)] internal Parent Parent; private Child() { } public Child(int i) { } } [ProtoContract()] public class Parent { [ProtoMember(1)] protected List m_Children; ///  /// ProtoBuf deserialization constructor (fails here) ///  private Parent() { m_Children = new List(); } public Parent(List children) { m_Children = children; m_Children.ForEach(x => x.Parent = this); } } [ProtoContract()] public class Family { [ProtoMember(1)] protected List m_Parents; public void Add(Parent parent) { m_Parents.Add(parent); } public Family() { m_Parents = new List(); } } } 

在反序列化期间,我遇到了exception“没有为此对象定义的无参数构造函数”。 用于在ProtoBuf.BclHelper附近创建Parent对象

 case FieldObject: // ... value = ((options & NetObjectOptions.UseConstructor) == 0) ? BclHelpers.GetUninitializedObject(type) : Activator.CreateInstance(type); 

然后,当我将默认构造函数Parent()更改为public时,exception消失。

知道我可能忽略的是在这种情况下AsRerference的正确用法是什么?

BOUNTY :虽然Marc花时间来解决这个问题,但我需要一个明确的解决方案来在这种情况下使用protobuf-net,通过protobuf-net属性,方法或其他技巧来解决。 否则我将不得不放弃使用protobuf-net。 谢谢你的帮助。

我相信你可以这样做来解决这个问题:

 [ProtoContract(SkipConstructor = true)] public class Parent { [ProtoMember(1)] protected List m_Children; private Parent() { Initialize(); } [ProtoBeforeDeserialization] // could also use OnDeserializing private void Initialize() { m_Children = new List(); } public Parent(List children) { m_Children = children; m_Children.ForEach(x => x.Parent = this); } 

}

反序列化Parent ,需要public parameterlessless构造函数。 因此,失败的最小测试用例是:创建具有非空m_Parent ,将其序列化并反序列化结果。