public static List<Type> GetFilteredTypesFromAssemblies(string cacheName, Predicate<Type> predicate, IBuildManager buildManager)
        {
            HttpControllerTypeCacheSerializer serializer = new HttpControllerTypeCacheSerializer();

            // first, try reading from the cache on disk
            List<Type> matchingTypes = ReadTypesFromCache(cacheName, predicate, buildManager, serializer);
            if (matchingTypes != null)
            {
                return matchingTypes;
            }

            // if reading from the cache failed, enumerate over every assembly looking for a matching type
            matchingTypes = FilterTypesInAssemblies(buildManager, predicate).ToList();

            // finally, save the cache back to disk
            SaveTypesToCache(cacheName, matchingTypes, buildManager, serializer);

            return matchingTypes;
        }
 private static void SaveTypesToCache(string cacheName, IList<Type> matchingTypes, IBuildManager buildManager, HttpControllerTypeCacheSerializer serializer)
 {
     try
     {
         Stream stream = buildManager.CreateCachedFile(cacheName);
         if (stream != null)
         {
             using (StreamWriter writer = new StreamWriter(stream))
             {
                 serializer.SerializeTypes(matchingTypes, writer);
             }
         }
     }
     catch
     {
         // cache failures are not considered fatal -- keep running.
     }
 }
        private static List<Type> ReadTypesFromCache(string cacheName, Predicate<Type> predicate, IBuildManager buildManager, HttpControllerTypeCacheSerializer serializer)
        {
            try
            {
                Stream stream = buildManager.ReadCachedFile(cacheName);
                if (stream != null)
                {
                    using (StreamReader reader = new StreamReader(stream))
                    {
                        List<Type> deserializedTypes = serializer.DeserializeTypes(reader);
                        if (deserializedTypes != null && deserializedTypes.All(type => predicate(type)))
                        {
                            // If all read types still match the predicate, success!
                            return deserializedTypes;
                        }
                    }
                }
            }
            catch
            {
                // cache failures are not considered fatal -- keep running.
            }

            return null;
        }