要系列化與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); }
}
}
這應該爲大多數你在它扔,除了object
T
工作。任何不尋常的對象本身都可能是數據合同。
爲V2
注:
- 你不需要的屬性;可所有在運行時
- 指定你不需要參數的構造函數(儘管它可能是最簡單的,以保持一個,使
children
啓動容易)
- 列表可以是不通用的,
IEnumerable
和Add(object)
(但預期類型必須指定)
有什麼錯誤?這棵樹看起來像什麼?樂意幫忙,但是有點模糊...... –
我編輯了q。我還有一個錯誤,但我不記得是哪一個。謝謝 – david
作爲參考,如果你包括@marc,那麼我會自動得到一些東西告訴我你已經回覆。我不需要補充一點,因爲我正在回覆您的*帖子*。我只提到它的原因是我只是看到了這一點,記得回頭看看。現在看... –