public bool TryAddItem(MediaItem item, IRelationshipRoleExtractor itemMatcher)
        {
            ICollection <string> identifiers = itemMatcher.GetExternalIdentifiers(item.Aspects);

            //We can only cache using external identifiers
            if (identifiers == null || identifiers.Count == 0)
            {
                return(false);
            }

            //Lazily created below
            CacheItem cacheItem = null;

            foreach (string identifier in identifiers)
            {
                IList <CacheItem> cacheList;
                if (!_cache.TryGetValue(identifier, out cacheList))
                {
                    //Identifier has never been cached, add it
                    cacheList = new List <CacheItem>();
                    _cache.Add(identifier, cacheList);
                }
                else if (cacheList.Any(c => c.Id == item.MediaItemId))
                {
                    //Already cached under this identifier
                    continue;
                }

                //Create the cache item if not already created.
                //Only the minimum number of aspects required by the itemMatcher
                //will be cached to avoid caching large thumbnails, etc
                if (cacheItem == null)
                {
                    cacheItem = CreateCacheItem(item, itemMatcher);
                }

                cacheList.Add(cacheItem);
            }

            if (cacheItem == null)
            {
                return(false);
            }

            //Item was added, add it to the cache history
            _cacheHistory.Add(item.MediaItemId);
            return(true);
        }
        public bool TryGetItemId(IDictionary <Guid, IList <MediaItemAspect> > aspects, IRelationshipRoleExtractor itemMatcher, out Guid mediaItemId)
        {
            mediaItemId = Guid.Empty;
            ICollection <string> identifiers = itemMatcher.GetExternalIdentifiers(aspects);

            //We can only match using external identifiers
            if (identifiers == null || identifiers.Count == 0)
            {
                return(false);
            }

            //All items that have been checked under the identifiers but didn't match
            ICollection <Guid> checkedIds = new HashSet <Guid>();

            foreach (string identifier in identifiers)
            {
                IList <CacheItem> cacheList;
                //Is the identifier in the cache?
                if (!_cache.TryGetValue(identifier, out cacheList))
                {
                    continue;
                }

                //Multiple media items can be cached under the same external identifier, we need
                //to delegate the actual matching to the itemMatcher
                foreach (CacheItem item in cacheList)
                {
                    //The same media items can appear under each identifier, don't bother checking
                    //any items that we've already checked.
                    if (checkedIds.Contains(item.Id))
                    {
                        continue;
                    }

                    if (itemMatcher.TryMatch(aspects, item.Aspects))
                    {
                        mediaItemId = item.Id;
                        return(true);
                    }
                    //Store this unmatching id so it's not checked again
                    checkedIds.Add(item.Id);
                }
            }
            return(false);
        }