如何通过protobuf避免在WCF中出现重复的对象

时间:2017-07-17 11:54:28

标签: wcf protocol-buffers protobuf-net

我是一个小单元测试来测试循环依赖。

我的目标如下:

[ProtoContract]
public class Node
{
    [ProtoMember(1)]
    public String Name { get; set; }

    [ProtoMember(2,AsReference = true)]
    public List<Node> Childs { get; set; }

    public Node()
    {
        Childs = new List<Node>();
    }
}

以下服务:

[ServiceContract]
public interface INodeService : IService
{
    [OperationContract]
    Task<Node> GetCyclicNodes();
}

public class NodeService : Service, INodeService
{
    public async Task<int> Add(int a, int b)
    {
        return a + b;
    }

    public async Task<Node> GetCyclicNodes()
    {
        Node nodeA = new Node() {Name = "Node A"};
        Node nodeB = new Node() {Name = "Node B"};
        Node nodeC = new Node() {Name = "Node C"};
        nodeA.Childs.Add(nodeB);
        nodeB.Childs.Add(nodeC);
        nodeC.Childs.Add(nodeA);
        return nodeA;
    }
}

在客户端,我计算对象的数量:

    private int CountNodes(Node node, List<Node> countedNodes = null)
    {
        if (countedNodes == null)
        {
            countedNodes = new List<Node>();
        }
        if (countedNodes.Contains(node))
        {
            return 0;
        }
        else
        {
            countedNodes.Add(node);
            int count = 1;
            foreach (Node nodeChild in node.Childs)
            {
                count += CountNodes(nodeChild, countedNodes);
            }
            return count;
        }
    }

当我调用它时,我希望接收整个层次结构,包含3个唯一对象实例(一个用于&#34;节点A和#34;,&#34;节点B&#34;,&#34;节点C&#34;。)

但似乎我有4个不同的对象,是对象A的两倍。

由于我的班级不是AsReferenceDefault,我有点担心它看不到它与它得到的对象相同。

就我而言,我是一个非常大的商业模式(约500种不同的模型),它们都来自同一个根类。每个类在技术上(在模型的角度来看)都可以被另一个类引用,它总是非常清楚每个类只有一个且只有一个所有者,而其他类只是指它。 这是我可以用protobuf做的事吗?

因为即使我不知道在使用引用时幕后发生了什么,我有点害怕它意味着每个字段都会放置一个唯一的ID,即使它们没有被引用

修改

事实上,即使在AsReferenceDefault = true上设置ProtoContract,我仍然会获得4个对象而不是3个,现在我有点迷失了。

编辑2

我做了另一个测试,我尝试了一个Container类(我的不同操作现在返回一些Task<Container<Node>>。这个Container只包含一个标记为AsReference = true的属性。现在它可以工作了,我和#39;只有3个实例。

但似乎暗示我没有正确理解AsReference机制。我以为有可能有一个&#34;所有者&#34;未标记AsReference=true的对象,以及引用此对象的所有其他对象将为AsReference =true。但如果我理解正确,这将导致有两个不同的实例?

如果是,我不明白将AsReference = true设置为AsReferenceDefault的优势吗?

我理解得对吗?

1 个答案:

答案 0 :(得分:1)

对我来说,看起来问题类似于this question,我们意识到根级实体存在问题。

我们还得到的是,对于子对象,引用的位置是正确的,但是如果再次引用了根项,则在反序列化后副本就在那里。

我们使用了一段时间(然后我们切换到纯JSON)的解决方法是添加一个额外的根节点。使用这个额外的根节点引用正确的deseriliazed。所以这可能是你可以尝试的解决方法。