/// <summary>
 /// Reset the visitor in order to use it to generate another model.
 /// </summary>
 public override void Reset()
 {
     rootNode = null;
     rootGuid = Guid.Empty;
     contextStack.Clear();
     referenceContents.Clear();
     base.Reset();
 }
 public override void Reset()
 {
     contextStack.Clear();
     rootNode = null;
     references.Clear();
     checkedNodes.Clear();
     base.Reset();
 }
Beispiel #3
0
        /// <summary>
        /// Add a child to this node. The node must not have been sealed yet.
        /// </summary>
        /// <param name="child">The child node to add.</param>
        /// <param name="allowIfReference">if set to <c>false</c> throw an exception if <see cref="IContent.Reference"/> is not null.</param>
        public void AddChild(ModelNode child, bool allowIfReference = false)
        {
            if (isSealed)
                throw new InvalidOperationException("Unable to add a child to a ModelNode that has been sealed");

            if (child.Parent != null)
                throw new ArgumentException(@"This node has already been registered to a different parent", "child");

            if (Content.Reference != null && !allowIfReference)
                throw new InvalidOperationException("A ModelNode cannot have children when its content hold a reference.");

            child.Parent = this;
            children.Add(child);
        }
        public void Check(ModelNode node, object obj, Type type, bool checkReferences)
        {
            Reset();

            if (node.Content.Value != obj)
                throw new QuantumConsistencyException("The node content value [{0}]", obj.ToStringSafe(), "The node content value [{0}]", node.Content.Value.ToStringSafe(), node);
            if (node.Content.Type != type)
                throw new QuantumConsistencyException("The node content type [{0}]", type.Name, "The node content value [{0}]", node.Content.Type.Name, node);

            rootNode = node;

            while (rootNode != null)
            {
                if (rootNode.Parent != null)
                    throw new QuantumConsistencyException("A root node", "A node with a parent", rootNode);

                if (rootNode.Content.Value != null)
                {
                    var typeDescriptor = TypeDescriptorFactory.Find(rootNode.Content.Type);
                    PushContextNode(rootNode);
                    VisitObject(rootNode.Content.Value, typeDescriptor as ObjectDescriptor, true);
                    PopContextNode();
                }
                checkedNodes.Add(rootNode);
                rootNode = null;

                if (checkReferences)
                {
                    while (references.Count > 0)
                    {
                        var reference = references.Dequeue();
                        if (!checkedNodes.Contains(reference.TargetNode))
                        {
                            rootNode = (ModelNode)reference.TargetNode;
                            break;
                        }
                    }
                }
            }
        }
 private void PushContextNode(ModelNode node)
 {
     contextStack.Push(node);
 }
        /// <inheritdoc/>
        public override void VisitObject(object obj, ObjectDescriptor descriptor, bool visitMembers)
        {
            ITypeDescriptor currentDescriptor = descriptor;

            bool isRootNode = contextStack.Count == 0;
            if (isRootNode)
            {
                bool shouldProcessReference;
                if (!NotifyNodeConstructing(descriptor, out shouldProcessReference))
                    return;

                // If we are in the case of a collection of collections, we might have a root node that is actually an enumerable reference
                // This would be the case for each collection within the base collection.
                IContent content = descriptor.Type.IsStruct() ? ContentFactory.CreateBoxedContent(this, obj, descriptor, IsPrimitiveType(descriptor.Type))
                                                : ContentFactory.CreateObjectContent(this, obj, descriptor, IsPrimitiveType(descriptor.Type), shouldProcessReference);
                currentDescriptor = content.Descriptor;
                rootNode = new ModelNode(currentDescriptor.Type.Name, content, rootGuid);
                if (content.IsReference && currentDescriptor.Type.IsStruct())
                    throw new QuantumConsistencyException("A collection type", "A structure type", rootNode);

                if (content.IsReference)
                    referenceContents.Add(content);

                AvailableCommands.Where(x => x.CanAttach(currentDescriptor, null)).ForEach(rootNode.AddCommand);
                NotifyNodeConstructed(content);

                if (obj == null)
                {
                    rootNode.Seal();
                    return;
                }
                PushContextNode(rootNode);
            }

            if (!IsPrimitiveType(currentDescriptor.Type))
            {
                base.VisitObject(obj, descriptor, (GetContextNode().Flags & ModelNodeFlags.DoNotVisitMembers) == 0);
            }

            if (isRootNode)
            {
                PopContextNode();
                rootNode.Seal();
            }
        }
        /// <inheritdoc/>
        public override void VisitObjectMember(object container, ObjectDescriptor containerDescriptor, IMemberDescriptor member, object value)
        {
            bool shouldProcessReference;
            if (!NotifyNodeConstructing(containerDescriptor, member, out shouldProcessReference))
                return;

            // If this member should contains a reference, create it now.
            ModelNode containerNode = GetContextNode();
            IContent content = ContentFactory.CreateMemberContent(this, containerNode.Content, member, IsPrimitiveType(member.Type), value, shouldProcessReference);
            var node = new ModelNode(member.Name, content, Guid.NewGuid());
            containerNode.AddChild(node);

            if (content.IsReference)
                referenceContents.Add(content);

            PushContextNode(node);
            if (!(content.Reference is ObjectReference))
            {
                // For enumerable references, we visit the member to allow VisitCollection or VisitDictionary to enrich correctly the node.
                Visit(content.Value);
            }
            PopContextNode();

            AvailableCommands.Where(x => x.CanAttach(node.Content.Descriptor, (MemberDescriptorBase)member)).ForEach(node.AddCommand);
            NotifyNodeConstructed(content);

            node.Seal();
        }
Beispiel #8
0
 private void PushContextNode(ModelNode node)
 {
     contextStack.Push(node);
 }