【问题标题】:How to avoid having duplicate objects in WCF over protobuf如何避免在 protobuf 上的 WCF 中有重复的对象
【发布时间】:2017-07-17 11:54:28
【问题描述】:

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

我的对象如下:

[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 个唯一对象实例(一个用于“节点 A”、“节点 B”、“节点 C”)。

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

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

就我而言,我有一个非常大的商业模式(约 500 种不同的模式),它们都继承自同一个根类。每个类都可以在技术上(从模型的角度)被另一个引用,很明显每个类都是唯一的所有者,而其他的只是引用它。 这是我可以用 protobuf 做的事情吗?

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

编辑

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

编辑 2

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

但似乎暗示我没有正确理解AsReference 机制。我在想可能有一个对象的“所有者”,它没有用AsReference=true 标记,所有其他也引用这个对象的对象都是AsReference =true。但如果我理解正确,这将导致有 2 个不同的实例?

如果是,我不明白设置AsReference = true 相对于AsReferenceDefault 的优势?

我理解正确吗?

【问题讨论】:

  • @MarcGravell 你有没有机会检查这个错误。我们还有很多其他情况,设置 AsReferenceDefault=true 是不够的。

标签: wcf protocol-buffers protobuf-net


【解决方案1】:

在我看来,这个问题与this question 类似,我们意识到根级实体存在问题。

我们还拥有的是,对于子对象,引用正确,但如果再次引用根项目,则在反序列化后存在副本。

我们使用了一段时间(然后我们切换到纯 JSON)的解决方法是添加一个额外的根节点。使用这个额外的根节点引用正确反序列化。因此,这可能是您也可以尝试的解决方法。

【讨论】:

  • 是的,这就是我所做的,但它并没有真正解决或让我理解它为什么会这样
  • 据我了解,这是 Protobuf 中的一个错误,但我还无法说服 @MarcGravel,他也对这个问题发表了评论。我们真的应该跟进。
  • 我在 github 上查找了现有问题,但没有找到。我在 github 上创建了一个新的 issue。如果缺少某些内容(或错误),请添加您的 cmets。
  • 你好;谢谢-我看到了问题,也看到了赏金-我只是没有时间深入研究它;不过,它在我的清单上非常值得一看,而且我已经回复了 git 帖子。以防万一@J4N 认为他们浪费了一笔赏金:你没有 - 我看到它并理解它导致了问题,所以:“收到消息” - 但我在过去几天根本没有空位。
  • @MarcGravell Ahah 没问题,只是我们这里有 4 个人等着我去实现 WCF 中的所有 .Net 远程服务,我想知道我们必须做的一切是否可以使用 protobuf还是有问题阻止我们使用它。 (而且我真的不在乎赏金;))
猜你喜欢
  • 2015-07-30
  • 2023-02-02
  • 2015-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-27
  • 1970-01-01
  • 2010-09-10
相关资源
最近更新 更多