ProtoBuf-net忽略" IgnoreListHandling"

时间:2013-12-04 12:21:55

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

我有一个名为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”方法中,这是没有的重要性。它将一个对象作为参数,并尝试将该类型转换为其中一个可存储的数据类型,并将其存储为强类型的PrimitiveSurrogate。实体基类只提供一个Name-property,而不是其他任何东西。

但是只要我将IEnumerable<ConfigNode>添加到接口列表并添加适当的方法(见下文),任何序列化尝试都会抛出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-flag,有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

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

现在(de)顺利序列化。

修正版:

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