/// <summary>
        /// Gets the ancestors of a node including itself.
        /// </summary>
        /// <param name="tree">
        /// The tree.
        /// </param>
        /// <param name="predicate">
        /// The predicate.
        /// </param>
        /// <typeparam name="TNode">
        /// The type of the tree node value
        /// </typeparam>
        /// <returns>
        /// The <see cref="IEnumerable{TreeNode}"/>.
        /// </returns>
        internal static IEnumerable<TreeNode<TNode>> AncestorsOrSelf<TNode>(
            this TreeNode<TNode> tree,
            Expression<Func<TreeNode<TNode>, bool>> predicate = null) where TNode : IHasKeyId
        {
            if (tree.Parent == null) return Enumerable.Empty<TreeNode<TNode>>();
            var visitor = new NodeAggregatorTreeNodeVisitor<TNode>();
            tree.Climb(visitor);

            var nodes = visitor.Nodes.AsQueryable();

            return predicate == null ? nodes : nodes.Where(predicate);
        }
        /// <summary>
        /// Gets the descendants of a node.
        /// </summary>
        /// <param name="tree">
        /// The tree.
        /// </param>
        /// <param name="predicate">
        /// The predicate.
        /// </param>
        /// <typeparam name="TNode">
        /// The type of the tree node value
        /// </typeparam>
        /// <returns>
        /// The <see cref="IEnumerable{TreeNode}"/>.
        /// </returns>
        internal static IEnumerable<TreeNode<TNode>> Descendants<TNode>(
            this TreeNode<TNode> tree,
            Expression<Func<TreeNode<TNode>, bool>> predicate = null)
            where TNode : IHasKeyId
        {
            var visitor = new NodeAggregatorTreeNodeVisitor<TNode>();
            tree.Traverse(visitor);

            // the visitor will pick up the tree itself in the traversal so we have to remove it
            var nodes = visitor.Nodes.Where(x => x.Value.Key != tree.Value.Key).AsQueryable();

            return predicate == null ? nodes : nodes.Where(predicate);
        }