/// <summary>
        /// Adds a minimum set of ASP.NET output cache dependencies for a view that contains data from pages of the specified runtime type.
        /// When any page of the specified runtime type is created, updated or deleted, the corresponding output cache item is invalidated.
        /// </summary>
        /// <param name="pages">Pages used to create validation callback to invalidate cache based on <see cref="TreeNode.DocumentPublishTo"/>.</param>
        /// <typeparam name="T">Runtime type that represents pages, i.e. it is derived from the <see cref="TreeNode"/> class.</typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="pages"/> is <c>null</c>.</exception>
        public void AddDependencyOnPages <T>(IEnumerable <T> pages) where T : TreeNode, new()
        {
            if (pages == null)
            {
                throw new ArgumentNullException(nameof(pages));
            }

            if (!mCacheEnabled)
            {
                return;
            }

            if (!pages.Any())
            {
                var dependencyCacheKey = GetDependencyCacheKeyForEmptyPagesRuntimeType <T>();
                AddCacheItemDependency(dependencyCacheKey);
            }
            else
            {
                var classNames = pages.Select(page => page.ClassName).Distinct();

                foreach (var className in classNames)
                {
                    var dependencyCacheKey = CacheDependencyKeyProvider.GetDependencyCacheKeyForPageType(SiteContext.CurrentSiteName, className);
                    AddCacheItemDependency(dependencyCacheKey);
                }

                AddCacheItemDependency("cms.adhocrelationship|all");
                AddCacheItemDependency("cms.relationship|all");

                AddValidationCallback(pages);
            }
        }
        private static CMSCacheDependency GetCacheDependency(string[] dependencyCacheKeys, IEnumerable <BaseInfo> objects)
        {
            var objectType = objects.First().TypeInfo.ObjectType;

            dependencyCacheKeys = dependencyCacheKeys ?? new[]
            {
                CacheDependencyKeyProvider.GetDependencyCacheKeyForObjectType(objectType)
            }
            ;

            return(CacheHelper.GetCacheDependency(dependencyCacheKeys));
        }
        private static CMSCacheDependency GetPagesCacheDependency(string[] dependencyCacheKeys, IEnumerable <TreeNode> pages)
        {
            var className = pages.First().ClassName;

            dependencyCacheKeys = dependencyCacheKeys ?? new[]
            {
                CacheDependencyKeyProvider.GetDependencyCacheKeyForPageType(SiteContext.CurrentSiteName, className),
                CacheDependencyKeyProvider.GetDependencyCacheKeyForObjectType(className)
            };

            var keys     = new HashSet <string>(dependencyCacheKeys, StringComparer.OrdinalIgnoreCase);
            var pathKeys = pages.Where(page => page.HasUrl())
                           .Select(page => page.NodeAliasPath)
                           .SelectMany(path => DocumentDependencyCacheKeysBuilder.GetParentPathsDependencyCacheKeys(SiteContext.CurrentSiteName, path))
                           .Distinct();

            foreach (var pathKey in pathKeys)
            {
                keys.Add(pathKey);
            }

            return(CacheHelper.GetCacheDependency(keys));
        }
        private string GetDependencyCacheKeyForEmptyPagesRuntimeType <T>() where T : TreeNode, new()
        {
            var className = mContentItemMetadataProvider.GetClassNameFromPageRuntimeType <T>();

            return(CacheDependencyKeyProvider.GetDependencyCacheKeyForPageType(SiteContext.CurrentSiteName, className));
        }