private IEnumerable <FileSystemInfo> ListAllFileSystemInfo(FileSystemInfo fileSystemInfo, int level) { var directoryInfo = fileSystemInfo as DirectoryInfo; var isRoot = level == -1; // Return the folder, or if it is the file, always. Skip the root level. if (!isRoot && (directoryInfo == null || _engineOptions.SearchIncludesFolders)) { yield return(fileSystemInfo); } if (directoryInfo != null && (_engineOptions.SearchRecursive || isRoot)) // Only if recursive or if the level is the root. { FileSystemInfo[] infos = null; try { infos = directoryInfo.GetFileSystemInfos(); } catch (UnauthorizedAccessException ex) { _expections.Add(SearchExceptionFactory.Build(directoryInfo, ex)); } if (infos == null) { yield break; } foreach (var item in infos.SelectMany(s => ListAllFileSystemInfo(s, level + 1))) { if (_stop) { yield break; } yield return(item); } } }
private IList <SearchResult> Search(object state) { var timer = (TimedCallback <SearchResult>)state; var criteria = BuildCriteria(); var list = new List <SearchResult>(64); var requiresPostProcessing = criteria.Any(c => c is IPostProcessingCriterion); foreach (var rootDirectory in _engineOptions.RootDirectories) { foreach (var fileSystemInfo in ListAllFileSystemInfo(rootDirectory, -1)) { var contexts = new Dictionary <Type, ICriterionContext>(); var isDir = fileSystemInfo is DirectoryInfo; var match = true; try { foreach (var c in criteria) { var context = c.BuildContext(); // Check if the criterion support the target file system type. if ((c.DirectorySupport && isDir) || (c.FileSupport && !isDir)) { if (c.IsMatch(fileSystemInfo, context)) { // Add the context if it is a match. if (context != null) { contexts.Add(c.GetType(), context); } } else { match = false; break; } } } } catch (Exception ex) { _expections.Add(SearchExceptionFactory.Build(fileSystemInfo, ex)); match = false; } if (match && !requiresPostProcessing) { list.Add(new SearchResult(fileSystemInfo) { Metadata = contexts }); } // Is match, and a result is not important. if (list.Count > 0 && !requiresPostProcessing && timer.DataNeeded) { timer.SetData(list); list = new List <SearchResult>(64); } // Stop the loop if (_stop) { break; } } // Stop the loop if (_stop) { break; } } if (requiresPostProcessing) { // Pick the last one, this is the most intensive criterion. var resultLists = criteria.OfType <IPostProcessingCriterion>().Single(); return(resultLists.PostProcess().ToList()); } return(list); }