【问题标题】:ProtoBuf-net ignores "IgnoreListHandling"ProtoBuf-net 忽略“IgnoreListHandling”
【发布时间】:2013-12-04 12:21:54
【问题描述】:

我有一个名为ConfigNode(类似于SerializationInfo)的树结构类,它可以将配置值存储在列表中并控制子节点。当我添加IEnumerable<ConfigNode> 作为派生接口时,protobuf-net 在序列化期间失败并导致 StackOverFlowException,即使 IgnoreListHandling 标志设置为 true。

[Serializable, DataContract, ProtoContract(IgnoreListHandling = true)]
public class ConfigNode : Entity, ICloneable, INotifyPropertyChanged
{
    [DataMember, ProtoMember(1)]
    private Dictionary<String, PrimitiveSurrogate> values = new Dictionary<String, PrimitiveSurrogate>();

    private Dictionary<String, ConfigNode> _Childs = new Dictionary<String, ConfigNode>();

    [DataMember, ProtoMember(2)]
    public Dictionary<String, ConfigNode> Childs
    {
        get
        {
            return _Childs;
        }
        private set
        {
            _Childs = value;
        }
    }

    [DataMember, ProtoMember(3)]
    public ConfigNode Parent { get; set; }
}

工作正常。 PrimitiveSurrogate 是一个存储所有常用“几乎原始”(如 String、Guid、DataTime、float / double、bool、char 等)的可空值的结构。配置值本身将添加到“Store”方法中,该方法是 no重要性。它将一个对象作为参数,并尝试将类型转换为一种可存储的数据类型,并将其存储为强类型 PrimitiveSurrogate。实体基类只提供一个名称属性,没有别的。

但只要我将IEnumerable&lt;ConfigNode&gt; 添加到接口列表并添加适当的方法(见下文),任何序列化尝试都会引发 StackOverflowException。

    public void Add(ConfigNode child)
    {
        if (child == null)
            throw new ArgumentNullException("child");
        if (child.Name == null)
            throw new ArgumentException("The child's name was null. The child cannot be added.");

        child.Parent = this;
        lock (this.Childs)
        {
            this.Childs[child.Name] = child;
        }
    }

    public IEnumerator<ConfigNode> GetEnumerator()
    {
        lock (this.Childs)
        {
            return this.Childs.Values.Clone().GetEnumerator();
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        lock (this.Childs)
        {
            return this.Childs.Values.Clone().GetEnumerator();
        }
    }

“克隆”是一种扩展方法,如下所示:

    public static IEnumerable<T> Clone<T>(this IEnumerable<T> collection)
    {
        return collection.ToList();
    }

似乎 protobuf-net 忽略了 IgnoreListHandling 标志,有人可以帮忙吗?

【问题讨论】:

    标签: c# serialization protocol-buffers protobuf-net


    【解决方案1】:

    没关系,我发现了错误。经过一些更改后,我在 Childs-Property 和 Childs.get() 中引入了一个锁,我锁定了属性本身而不是支持字段。由于 Monitor-Class 尝试访问该属性并导致再次访问 get-Accessor,这导致了 StackOverflow。

    它现在(反)序列化顺利。

    固定版本:

    [DataMember, ProtoMember(2)]
    public Dictionary<String, ConfigNode> Childs
    {
        get
        {
            lock (_Childs)
            {
                return _Childs;
            }
        }
        private set
        {
            lock (_Childs)
            {
                _Childs = value;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-11
      • 2011-11-27
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多