ProtoBuf-net在Activator.CreateInstance中需要公共构造函数

本文关键字:构造函数 Activator CreateInstance ProtoBuf-net | 更新日期: 2023-09-27 18:06:55

当我在我的2类看起来像这样(最小)

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<Child>() { 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<Family>(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<Child> m_Children;
        /// <summary>
        /// ProtoBuf deserialization constructor (fails here)
        /// </summary>
        private Parent() { m_Children = new List<Child>(); }
        public Parent(List<Child> children)
        {
            m_Children = children;
            m_Children.ForEach(x => x.Parent = this);
        }
    }
    [ProtoContract()]
    public class Family
    {
        [ProtoMember(1)]
        protected List<Parent> m_Parents;
        public void Add(Parent parent)
        {
            m_Parents.Add(parent);
        }
        public Family()
        {
            m_Parents = new List<Parent>();
        }
    }
}

在反序列化过程中,我遇到了在ProtoBuf中创建父对象的异常"没有为这个对象定义无参数构造函数"。BclHelper附近

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

当我将默认构造函数Parent()更改为public时,异常就消失了。

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

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

ProtoBuf-net在Activator.CreateInstance中需要公共构造函数

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

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

}

当您反序列化Parent时,您需要公共无参数构造函数。因此,失败的最小测试用例是:创建具有非空m_ParentChild,对其进行序列化并对结果进行反序列化。