private static T[] GetAll___ <T>( Assembly a, string discriminator, Func <IEnumerable <string>, IEnumerable <T> > decode, Func <IEnumerable <Type>, IEnumerable <T> > createResult, Func <T[], IEnumerable <string> > encode ) { var assemblyFileName = a.Location; var cacheFileName = CreateCacheFileName(assemblyFileName, discriminator.ToGuid()); var assemblyTimeStamp = File.GetLastWriteTimeUtc(assemblyFileName); if (File.Exists(cacheFileName)) { /* var cacheFileTimeStamp = */ File.GetLastWriteTimeUtc(cacheFileName); var lines = File.ReadAllLines(cacheFileName); var header = lines.Length > 0 ? CacheFileHeader.Parse(lines[0]) : null; if (header != null && header.TimeStampOfCachedFile == assemblyTimeStamp) { // return cached types Report.Line(4, "[cache hit ] {0}", a); return(decode(lines.Skip(1)).ToArray()); } } Report.Line(4, "[cache miss] {0}", a); // Notes by hs: // previously (rev 19495) typeloadexception resulted in empty result set. // even in case of typeloadexception there may be some successfully loaded // types in result set. Just continue processing with these types // effect: dlls with external unused dependencies don't have to be shipped. Type[] ts = new Type[0]; try { ts = a.GetTypes().ToArray(); } catch (ReflectionTypeLoadException e) { Report.Begin("ReflectionTypeLoadException error in assembly {0}", a.GetName().Name); Report.Line("Full assembly name is {0}.", a.FullName); Report.Line("Exception is {0}", e); Report.Begin("Loader exceptions are"); foreach (var x in e.LoaderExceptions) { Report.Line("{0}", x); } Report.End(); Report.End(); ts = e.Types.Where(t => t != null).ToArray(); } var result = createResult(ts).ToArray(); // write cache file var headerLine = new CacheFileHeader { Version = 1, TimeStampOfCachedFile = assemblyTimeStamp } .ToString() .IntoIEnumerable() ; File.WriteAllLines(cacheFileName, headerLine.Concat(encode(result)).ToArray()); return(result); }