static BuildSettingsSearcherDatabase Populate <T>(HashSet <Type> types, Func <Type, string> displayNameResolver) { var list = new List <SearcherItem>(); var dict = new Dictionary <string, SearcherItem>(); var collection = TypeCache.GetTypesDerivedFrom <T>(); foreach (var type in collection) { if (type.IsGenericType || type.IsAbstract || type.ContainsGenericParameters || type.IsInterface) { continue; } if (!TypeConstruction.HasParameterLessConstructor(type)) { continue; } try { if (types.Contains(type)) { continue; } var category = string.Empty; TypeSearcherItem typeItem = null; // Fully type-based if (null == displayNameResolver) { typeItem = new TypeSearcherItem(type); category = type.Namespace ?? "Global"; } // We control the naming else { var displayName = displayNameResolver.Invoke(type); var prefixIndex = displayName.IndexOf("/", StringComparison.InvariantCultureIgnoreCase); category = prefixIndex >= 0 ? displayName.Substring(0, prefixIndex) : "Other"; var name = displayName.Substring(prefixIndex >= 0 ? prefixIndex + 1 : 0); typeItem = new TypeSearcherItem(type, name); } if (!dict.TryGetValue(category, out var item)) { dict[category] = item = new SearcherItem(category); list.Add(item); } item.AddChild(typeItem); } catch (Exception) { // ignored } } foreach (var kvp in dict) { kvp.Value.Children.Sort(CompareByName); } list.Sort(CompareByName); return(new BuildSettingsSearcherDatabase(list)); }