protected ContextNode CreateNode(int i, Guid id, ContextValue cv, ContextNode node, Type type) { if (i == cv.TypePath.Count - 1) { // At this point, node.Children[].Type && node.Children[].ContextValue.RecordNumber must be unique! Assert.That <ContextValueDictionaryException>(!node.Children.Any(c => c.Type == type && c.ContextValue.RecordNumber == cv.RecordNumber), "ContextValue type and record number must be unique to parent context."); } ContextNode childNode = new ContextNode(id, type); node.AddChild(childNode); // Since we're creating a node, add it to the flat tree view. if (!flatView.TryGetValue(type, out List <ContextNode> nodes)) { flatView[type] = new List <ContextNode>(); } flatView[type].Add(childNode); return(childNode); }
public void AddOrUpdate(ContextValue cv) { // We have to process this synchronously! // If async, we might get simultaneous requests (particularly from the browser's async PUT calls) to add a value. // While we're constructing the dictionary entry for one context path, another request might come in before we've // created all the nodes for the first call. lock (this) { // Walk the instance/path, creating new nodes in the context tree as required. Assert.That(cv.TypePath.Count == cv.InstancePath.Count, "type path and instance path should have the same number of entries."); ContextNode node = tree; for (int i = 0; i < cv.TypePath.Count; i++) { // Walk the tree. var(id, type) = (cv.InstancePath[i], cv.TypePath[i]); if (node.Children.TryGetSingle(c => c.InstanceId == id, out ContextNode childNode)) { node = childNode; } else { // Are we referencing an existing sub-context? if (flatView.TryGetValue(type, out List <ContextNode> nodes)) { // The instance path of the node must match all the remaining instance paths in the context // we're adding/updating! bool foundExistingSubContext = false; foreach (var fvnode in nodes) { foreach (var fvnodepath in fvnode.ChildInstancePaths()) { if (cv.InstancePath.Skip(i).SequenceEqual(fvnodepath)) { // This node get's a child referencing the existing sub-context node. node.AddChild(fvnode); node = fvnode; foundExistingSubContext = true; break; } } if (foundExistingSubContext) { break; } } if (!foundExistingSubContext) { node = CreateNode(i, id, cv, node, type); } } else { node = CreateNode(i, id, cv, node, type); } } } // The last entry in the tree gets the actual context value. We've either added this node to the tree // or updating an existing node. node.ContextValue = cv; } }