递归异常

时间:2012-02-19 01:32:47

标签: protobuf-net

我在这段代码中遇到了递归问题:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using ProtoBuf;

namespace ConsoleApplication4
{
[Serializable]
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class GeneralWrapper<T> where T : new()
{
    public GeneralWrapper()
    {
        Datas = new T();
    }

    public T Datas { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        List<Document> _documents = new List<Document>();

        for (int i = 0; i < 100000; i++)
        {
            Document _document = new Document()
            {
                DocumentName = "asdadsf"
            };

            _documents.Add(_document);
        }

        BinaryFormatter _formatter = new BinaryFormatter();

        FileStream fs = new FileStream
            ("Person1.bin", FileMode.OpenOrCreate);

        ProtoBuf.Serializer.Serialize(fs, _documents);

        fs.Close();

        // Deserialize.
        fs = new FileStream
            ("Person1.bin", FileMode.OpenOrCreate);

        List<Document> _document22 = ProtoBuf.Serializer.Deserialize<List<Document>>(fs);

        fs.Close();
    }
}

[ProtoContract]
public class Document
{
    public Document()
    {
        _count = 234234924;

        Section = new Section();

        Section.SectionName = "sdfasd";
    }

    [ProtoMember(1)]
    public string DocumentName { get; set; }

    [ProtoMember(2)]
    Dictionary<string, List<string>> Hello { get; set; }
    [ProtoMember(3, AsReference=true)]
    public Section Section { get; set; }

    [ProtoMember(4)]
    private string _sectionName;
    [ProtoMember(5)]
    public string SectionName
    {
        get
        {
            return Section.SectionName;
        }

        set
        {
            _sectionName = value;

            Section.SectionName = _sectionName;
        }
    }

    public int _count;
    public int Count
    {
        get
        {
            return _count;
        }
    }
}

[Serializable]
[ProtoContract]
public class Section
{
    public Section()
    {
        Section1 = new SectionInner(this);

        Hellos = new List<GeneralWrapper<List<string>>>();

        GeneralWrapper<List<string>> _hello = new GeneralWrapper<List<string>>();

        _hello.Datas.Add("hello");

        Hellos.Add(_hello);

        DHello = new Dictionary<string, List<Section>>();

        if (!DHello.ContainsKey("asdf"))
        {
            List<Section> _dhello1 = new List<Section>();

            _dhello1.Add(this);

            DHello.Add("asdf", _dhello1);
        }
    }

    [ProtoMember(1, AsReference=true)]
    public SectionInner Section1 { get; set; }
    [ProtoMember(2)]
    public string SectionName { get; set; }

    [ProtoMember(3, AsReference=true)]
    public Dictionary<string, List<Section>> DHello { get; set; }

    List<GeneralWrapper<List<string>>> Hellos { get; set; }
}

[Serializable]
[ProtoContract]
public class SectionInner
{
    public SectionInner(Section section)
    {
        Section = section;
    }

    [ProtoMember(1, AsReference=true)]
    public Section Section { get; set; }
}

}

我显然在开始时使代码非常递归,因为它与我的真实项目正在做同样的事情。问题似乎是这样的:

 Dictionary<string, List<Section>>

当没有任何内容添加到这本词典时,所有内容都很好。如果使用某个键将列表添加到字典中,则会发生递归。

protobuf-net支持这种代码/语法吗?:

 Dictionary<string, List<Section>>

我是否需要将List放在外部包装类中,如:

 Dictionary<string, Wrapper<List<Section>>>

感谢您的帮助。我是protobuf-net的新手。

1 个答案:

答案 0 :(得分:2)

首先 - 我必须注意,在构造函数中执行那么多设置并不是一个好主意。如果这表示您的实际代码,您可能希望在反序列化期间跳过构造函数([ProtoContract(SkipConstructor=true)])。如果它只是说明性的,那很好。

是的,支持字典和列表之类的东西,但* 直接嵌套列表不是 - 所以目前List<List<...>>还不行。您可能会使用Dictionary<TKey,List<...>>来逃避它,因为它的键值对已经充当了中间的包装。

重新递归:protobuf-net支持许多递归方案,但这是正式规范的扩展。因此,您需要明确启用它,并注意:由于没有正式的规范,因此很难互换这种情况;但是:[ProtoMember(n, AsReference=true)]可以对单个成员进行对象跟踪。请注意,所有使用此对象的位置都必须标记为这样,否则它们将使用树序列化。

重新&#34;为什么不直接支持递归&#34; - 因为:protobuf(正式规范)的行为与此处的大多数序列化程序类似,并且是序列化程序。注意:诸如XmlSerializer,JavascriptSerializer和DataContractSerializer(在默认模式下)之类的东西是也是树序列化器,如果给定递归结构,它将会爆炸。这个是正常的。 protobuf-net在某些情况下不遗余力地允许这种情况,但默认情况下无法启用它,因为它需要不同的数据布局,从而无法实现跨平台数据规范的目的。

如果我错过了您的任何问题,请说出来。

相关问题