如何避免在 protobuf 上的 WCF 中有重复的对象
Posted
技术标签:
【中文标题】如何避免在 protobuf 上的 WCF 中有重复的对象【英文标题】:How to avoid having duplicate objects in WCF over protobuf 【发布时间】: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<Container<Node>>
。这个 Container 只包含一个标记为 AsReference = true
的属性。现在它可以工作了,我只有 3实例。
但似乎暗示我没有正确理解AsReference
机制。我在想可能有一个对象的“所有者”,它没有用AsReference=true
标记,所有其他也引用这个对象的对象都是AsReference =true
。但如果我理解正确,这将导致有 2 个不同的实例?
如果是,我不明白设置AsReference = true
相对于AsReferenceDefault
的优势?
我理解正确吗?
【问题讨论】:
@MarcGravell 你有没有机会检查这个错误。我们还有很多其他情况,设置AsReferenceDefault=true
是不够的。
【参考方案1】:
在我看来,这个问题与this question 类似,我们意识到根级实体存在问题。
我们还拥有的是,对于子对象,引用正确,但如果再次引用根项目,则在反序列化后存在副本。
我们使用了一段时间(然后我们切换到纯 JSON)的解决方法是添加一个额外的根节点。使用这个额外的根节点引用正确反序列化。因此,这可能是您也可以尝试的解决方法。
【讨论】:
是的,这就是我所做的,但它并没有真正解决或让我理解它为什么会这样 据我了解,这是 Protobuf 中的一个错误,但我还无法说服 @MarcGravel,他也对这个问题发表了评论。我们真的应该跟进。 我在 github 上查找了现有问题,但没有找到。我在 github 上创建了一个新的 issue。如果缺少某些内容(或错误),请添加您的 cmets。 你好;谢谢-我看到了问题,也看到了赏金-我只是没有时间深入研究它;不过,它在我的清单上非常值得一看,而且我已经回复了 git 帖子。以防万一@J4N 认为他们浪费了一笔赏金:你没有 - 我看到它并理解它导致了问题,所以:“收到消息” - 但我在过去几天根本没有空位。 @MarcGravell Ahah 没问题,只是我们这里有 4 个人等着我去实现 WCF 中的所有 .Net 远程服务,我想知道我们必须做的一切是否可以使用 protobuf还是有问题阻止我们使用它。 (而且我真的不在乎赏金;))以上是关于如何避免在 protobuf 上的 WCF 中有重复的对象的主要内容,如果未能解决你的问题,请参考以下文章