Serialization 用protobuf-net实现泛型树的序列化

Serialization 用protobuf-net实现泛型树的序列化,serialization,binary-tree,generics,protobuf-net,Serialization,Binary Tree,Generics,Protobuf Net,我尝试用各种对象(int、bool、list、dictionary等)构建二叉树,并对其进行序列化/反序列化 对于二进制formmater序列化,它运行良好,但是对于protobufnet,我遇到了错误 我不知道问题是与树的实现有关,还是与protobuf网络的使用有关 任何答案都会帮助我 谢谢 编辑 我尝试了我在网络中找到的两个版本的树代码 第一版 第二版 两个版本中的T是object 我得到的错误是: 没有找到合适的默认对象编码要用protobuf序列化,有一些关于如何映射成员的必要数据

我尝试用各种对象(int、bool、list、dictionary等)构建二叉树,并对其进行序列化/反序列化

对于二进制formmater序列化,它运行良好,但是对于protobufnet,我遇到了错误

我不知道问题是与树的实现有关,还是与protobuf网络的使用有关

任何答案都会帮助我
谢谢

编辑

我尝试了我在网络中找到的两个版本的树代码

第一版

第二版

两个版本中的T是object

我得到的错误是:
没有找到合适的默认对象编码

要用protobuf序列化,有一些关于如何映射成员的必要数据-请注意,每个成员本身必须对protobuf有意义,或者必须是某种列表

如果您可以显示您正在使用的确切树,我可以提供更多帮助,但例如:

    [ProtoContract]
    class Node<T>
    {
        [ProtoMember(1)]
        public T Value { get; set; }
        [ProtoMember(2, DataFormat= DataFormat.Group)]
        public List<Node<T>> Children { get { return children; } }
        private readonly List<Node<T>> children = new List<Node<T>>();
    }
除了
对象
之外,对于您抛出的大多数
T
都应该有效。任何异常对象本身都可能是数据契约

v2的注意事项:

  • 你不需要这些属性;这些都可以在运行时指定
  • 您不需要无参数构造函数(尽管保留一个构造函数可能是最容易的,以使
    子类
    初始化更容易)
  • 列表可以是非泛型、
    IEnumerable
    Add(object)
    (但必须指定预期的类型)

有哪些错误?这棵树看起来像什么?很乐意帮忙,但这有点含糊不清……我编辑了q。我又犯了一个错误,但我不记得是哪一个。谢谢你的参考如果你包括@marc,那么我会自动得到一些信息,告诉我你已经回复了。我不需要补充,因为我正在回复你的帖子。我提到它的唯一原因是我刚刚看到了这一点,记得回头看看。现在看…我想说得更清楚。当其中一些对象必须是字典时,我想向树中添加各种对象。
object
在不包含类型元数据的wire格式上很难支持。真的会有什么吗?还是“这一已知可能性中的一个”?最后一个是可行的,谢谢!刚刚看到,我稍后会试试。谢谢你详细的回答。是否有任何更改表明在V2中向树中添加Dicionary是合法的?@marc你说:V2的注释:你不需要属性;这些都可以在运行时指定。当我事先不知道t时,您能告诉我如何将节点添加到RuntimeTypeModel吗?对于Node或Node,这一点很明显。@Bartosz您仍然需要获得适当的
类型
信息,例如使用
typeof(Node)。MakeGenericType(typeOfT)
,或者
typeof(Node)
,如果您使用的是泛型
方法。谢谢,但这两种解决方案都有假设。首先:我必须事先知道
typeOfT
,其次我必须知道泛型方法。问题是当我有
节点时,
T
可以是一切。我认为,一定有解决方案,因为当我添加
ProtoContract
ProtoMember
属性时,就像上面的例子一样,它就工作了。
using System;
using System.Collections.Generic;
using ProtoBuf;


static class Program
{
    static void Main()
    {
        var tree = new NTree<int>(1);
        tree.addChild(2);
        var child = tree.addChild(3);
        tree.addChild(4);
        child.addChild(5);
        child.addChild(6).addChild(7);


        var clone = Serializer.DeepClone(tree);
        DrawTree(tree);
        Console.WriteLine();
        Console.WriteLine();
        DrawTree(clone);
    }
    static void DrawTree<T>(NTree<T> tree, int depth = 0)
    {
        var prefix = new string('\t', depth++);
        Console.WriteLine(prefix + tree.Data);
        foreach (var child in tree.Children) DrawTree(child, depth);
    }
}

[ProtoContract]
class NTree<T>
{
    [ProtoMember(1)]
    T data;
    LinkedList<NTree<T>> children;
    internal T Data { get { return data; } } // added for demo only
    internal IEnumerable<NTree<T>> Children { get { return children; } }// added for demo only
    public NTree(T data)
    {
        this.data = data;
        children = new LinkedList<NTree<T>>();
    }

    public NTree<T> addChild(T data) // changed just so I can build a tree for the demo
    {
        var child = new NTree<T>(data);
        children.AddFirst(child);
        return child;
    }

    public NTree<T> getChild(int i)
    {
        foreach (NTree<T> n in children)
            if (--i == 0) return n;
        return null;
    }

    private NTree()
    {
        children = new LinkedList<NTree<T>>();
    }

    [ProtoMember(2, DataFormat=DataFormat.Group)]
    private NodeWrapper WrappedChildren {
        get { return new NodeWrapper(children); }
    }
    private class NodeWrapper:IEnumerable<NTree<T>>
    { // only exists to help with serialization
        private readonly LinkedList<NTree<T>> nodes;

        public NodeWrapper(LinkedList<NTree<T>> nodes)
        {
            this.nodes = nodes;
        }
        public IEnumerator<NTree<T>> GetEnumerator()
        {
            return nodes.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return nodes.GetEnumerator();
        }
        public void Add(NTree<T> child) { nodes.AddLast(child); }
    }
}