我尝试使用各种对象(int,bool,list,dictionary等)构建二叉树并对其进行序列化/反序列化。
使用二进制formmater序列化它很好但是使用protobufnet我遇到了错误。
我不知道问题是关于树的实施还是使用protobuf-net。
任何答案都会对我有所帮助 感谢
修改
我尝试了在net
中找到的两个版本的树代码第一个版本 Tree data structure in C#
Seconed版本 http://msdn.microsoft.com/en-us/library/ms379572.aspx
两个版本的T是对象。
我得到的错误: 找不到合适的默认对象编码
答案 0 :(得分:2)
要使用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>>();
}
应序列化好。必要的数据也可以在运行时以“v2”提供。
部分基于电子邮件对话,我更了解模型,我看到的重要变化是:
最后一个是有趣的;我故意做出了不要求完整IList
/ IList<T>
的决定 - 它只需要IEnumerable<T>
和Add(T)
方法,所以我可以添加一个私有的包装器对象存在是为了序列化。
所以,根据电子邮件内容:
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); }
}
}
除了T
之外, 应该为你投掷的大多数object
工作。任何不寻常的对象本身应该是数据合同。
v2的注释:
children
启动容易)IEnumerable
和Add(object)
(但必须指定预期的类型)