/// <summary> /// Visits the children of the given node. /// </summary> /// <param name="node">The node being visited.</param> /// <param name="currentPath">The path of the node being visited.</param> protected virtual void VisitChildren(IGraphNode node, GraphNodePath currentPath) { foreach (var child in node.Children) { var childPath = currentPath.PushMember(child.Name); if (ShouldVisitNode(child.Content as MemberContent, child)) { VisitNode(child, childPath); } } }
/// <summary> /// Visits the children of the given node. /// </summary> /// <param name="node">The node being visited.</param> /// <param name="currentPath">The path of the node being visited.</param> public virtual void VisitChildren(IGraphNode node, GraphNodePath currentPath) { foreach (var child in node.Children) { var childPath = currentPath.PushMember(child.Name); if (ShouldVisitNode(child, childPath)) { VisitNode(child, childPath); } } }
/// <summary> /// Visits the children of the given node. /// </summary> /// <param name="node">The node being visited.</param> /// <param name="currentPath">The path of the node being visited.</param> protected virtual void VisitChildren(IObjectNode node, GraphNodePath currentPath) { foreach (var child in node.Members) { var childPath = currentPath.PushMember(child.Name); if (ShouldVisitNode(child, child)) { VisitNode(child, childPath); } } }
public static GraphNodePath From(IGraphNode root, MemberPath memberPath, out Index index) { var result = new GraphNodePath(root); index = Index.Empty; var memberPathItems = memberPath.Decompose(); for (int i = 0; i < memberPathItems.Count; i++) { var memberPathItem = memberPathItems[i]; bool lastItem = i == memberPathItems.Count - 1; if (memberPathItem.MemberDescriptor != null) { result = result.PushMember(memberPathItem.MemberDescriptor.Name); } else if (memberPathItem.GetIndex() != null) { var localIndex = new Index(memberPathItem.GetIndex()); if (lastItem) { // If last item, we directly return the index rather than add it to the path index = localIndex; } else { result = result.PushIndex(localIndex); } } // Don't apply Target on last item if (!lastItem) { // If this is a reference, add a target element to the path var node = result.GetNode(); var objectReference = node.Content.Reference as ObjectReference; if (objectReference?.TargetNode != null) { result = result.PushTarget(); } } } return(result); }
private void GenerateChildren(IGraphNode targetNode, GraphNodePath targetNodePath) { // Node representing a member with a reference to another object if (SourceNode != targetNode && SourceNode.Content.IsReference) { var objectReference = SourceNode.Content.Reference as ObjectReference; // Discard the children of the referenced object if requested by the property provider if (objectReference != null && !Owner.PropertiesProvider.ShouldExpandReference(SourceNode.Content as MemberContent, objectReference)) return; var refEnum = SourceNode.Content.Reference as ReferenceEnumerable; if (refEnum != null) { foreach (var reference in refEnum) { // Discard the children of the referenced object if requested by the property provider if (reference != null && !Owner.PropertiesProvider.ShouldExpandReference(SourceNode.Content as MemberContent, reference)) return; } } } var dictionary = targetNode.Content.Descriptor as DictionaryDescriptor; var list = targetNode.Content.Descriptor as CollectionDescriptor; // Node containing a collection of references to other objects if (SourceNode == targetNode && targetNode.Content.IsReference) { var referenceEnumerable = targetNode.Content.Reference as ReferenceEnumerable; if (referenceEnumerable != null) { // We create one node per item of the collection, unless requested by the property provide to not expand the reference. foreach (var reference in referenceEnumerable) { // The type might be a boxed primitive type, such as float, if the collection has object as generic argument. // In this case, we must set the actual type to have type converter working, since they usually can't convert // a boxed float to double for example. Otherwise, we don't want to have a node type that is value-dependent. var type = reference.TargetNode != null && reference.TargetNode.Content.IsPrimitive ? reference.TargetNode.Content.Type : reference.Type; var observableNode = Owner.ObservableViewModelService.ObservableNodeFactory(Owner, null, false, targetNode, targetNodePath, type, reference.Index); AddChild(observableNode); observableNode.Initialize(); } } } // Node containing a dictionary of primitive values else if (dictionary != null && targetNode.Content.Value != null) { // TODO: there is no way to discard items of such collections, without discarding the collection itself. Could this be needed at some point? // We create one node per item of the collection. foreach (var key in dictionary.GetKeys(targetNode.Content.Value)) { var index = new Index(key); var observableChild = Owner.ObservableViewModelService.ObservableNodeFactory(Owner, null, true, targetNode, targetNodePath, dictionary.ValueType, index); AddChild(observableChild); observableChild.Initialize(); } } // Node containing a list of primitive values else if (list != null && targetNode.Content.Value != null) { // TODO: there is no way to discard items of such collections, without discarding the collection itself. Could this be needed at some point? // We create one node per item of the collection. for (int i = 0; i < list.GetCollectionCount(targetNode.Content.Value); ++i) { var index = new Index(i); var observableChild = Owner.ObservableViewModelService.ObservableNodeFactory(Owner, null, true, targetNode, targetNodePath, list.ElementType, index); AddChild(observableChild); observableChild.Initialize(); } } // Node containing a single non-reference primitive object else { foreach (var child in targetNode.Children) { var memberContent = (MemberContent)child.Content; var descriptor = (MemberDescriptorBase)memberContent.Member; var displayAttribute = TypeDescriptorFactory.Default.AttributeRegistry.GetAttribute<DisplayAttribute>(descriptor.MemberInfo); if (displayAttribute == null || displayAttribute.Browsable) { // The path is the source path here - the target path might contain the target resolution that we don't want at that point if (Owner.PropertiesProvider.ShouldConstructMember(memberContent)) { var childPath = targetNodePath.PushMember(child.Name); var observableChild = Owner.ObservableViewModelService.ObservableNodeFactory(Owner, child.Name, child.Content.IsPrimitive, child, childPath, child.Content.Type, Index.Empty); AddChild(observableChild); observableChild.Initialize(); } } } } }