private bool VisitNodeReferences(esVisitParameters p)
        {
            Type type = p.Node.Obj.GetType();

            esVisitableNode parent = p.Parent;
            esVisitableNode node   = p.Node;

            p.Node   = new esVisitableNode();
            p.Parent = new esVisitableNode();

            try
            {
                if (!typeof(String).IsAssignableFrom(type) && typeof(IEnumerable).IsAssignableFrom(type))
                {
                    p.Parent = node;

                    int i = 0;
                    foreach (object item in (IEnumerable)node.Obj)
                    {
                        p.Node.Obj          = item;
                        p.Node.PropertyName = "";
                        p.ProcessChildren   = true;

                        if (!VisitNode(p))
                        {
                            return(false);
                        }
                        i++;
                    }
                }

                if (typeof(IVisitable).IsAssignableFrom(type))
                {
                    esVisitableNode[] nodes = ((IVisitable)node.Obj).GetGraph(enterCallback);
                    if (nodes != null)
                    {
                        p.Parent = node;

                        for (int i = 0; i < nodes.Length; i++)
                        {
                            p.Node = nodes[i];

                            p.ProcessChildren = true;
                            if (!VisitNode(p))
                            {
                                return(false);
                            }
                        }
                    }
                }
            }
            finally
            {
                p.Parent = parent;
                p.Node   = node;
            }

            return(true);
        }
        private bool Visit(object root, object userState, bool clearReferences)
        {
            if (clearReferences)
            {
                references.Clear();
            }

            esVisitParameters parameters = new esVisitParameters()
            {
                Root            = root,
                ProcessChildren = true,
                Node            = new esVisitableNode(root),
                Parent          = new esVisitableNode(),
                UserState       = userState
            };

            return(VisitNode(parameters));
        }
        private bool VisitNode(esVisitParameters p)
        {
            bool keepGoing = true;

            if (p.Node != null && AddIfNewReference(p.Node))
            {
                if (!enterCallback(p))
                {
                    keepGoing = false;
                }

                if (p.ProcessChildren && keepGoing && !VisitNodeReferences(p))
                {
                    keepGoing = false;
                }

                if (exitCallback != null && !exitCallback(p))
                {
                    keepGoing = false;
                }
            }

            return(keepGoing);
        }
        private bool Visit(object root, object userState, bool clearReferences)
        {
            if (clearReferences)
            {
                references.Clear();
            }

            esVisitParameters parameters = new esVisitParameters()
            {
                Root = root,
                ProcessChildren = true,
                Node = new esVisitableNode(root),
                Parent = new esVisitableNode(),
                UserState = userState
            };

            return VisitNode(parameters);
        }
        private bool VisitNodeReferences(esVisitParameters p)
        {
            Type type = p.Node.Obj.GetType();

            esVisitableNode parent = p.Parent;
            esVisitableNode node = p.Node;

            p.Node = new esVisitableNode();
            p.Parent = new esVisitableNode();

            try
            {
                if (!typeof(String).IsAssignableFrom(type) && typeof(IEnumerable).IsAssignableFrom(type))
                {
                    p.Parent = node;

                    int i = 0;
                    foreach (object item in (IEnumerable)node.Obj)
                    {
                        p.Node.Obj = item;
                        p.Node.PropertyName = "";
                        p.ProcessChildren = true;

                        if (!VisitNode(p))
                        {
                            return false;
                        }
                        i++;
                    }
                }

                if (typeof(IVisitable).IsAssignableFrom(type))
                {
                    esVisitableNode[] nodes = ((IVisitable)node.Obj).GetGraph(enterCallback);
                    if (nodes != null)
                    {
                        p.Parent = node;

                        for (int i = 0; i < nodes.Length; i++)
                        {
                            p.Node = nodes[i];

                            p.ProcessChildren = true;
                            if (!VisitNode(p))
                            {
                                return false;
                            }
                        }
                    }
                }
            }
            finally
            {
                p.Parent = parent;
                p.Node = node;
            }

            return true;
        }
        private bool VisitNode(esVisitParameters p)
        {
            bool keepGoing = true;

            if (p.Node != null && AddIfNewReference(p.Node))
            {
                if (!enterCallback(p))
                {
                    keepGoing = false;
                }

                if (p.ProcessChildren && keepGoing && !VisitNodeReferences(p))
                {
                    keepGoing = false;
                }

                if (exitCallback != null && !exitCallback(p))
                {
                    keepGoing = false;
                }
            }

            return keepGoing;
        }