public HelpInfo GetHelpInfo(HelpAdjacencyCriteria adjacencyCriteria) { Guard.AgainstNullArgument(nameof(adjacencyCriteria), adjacencyCriteria); if (!File.Exists(_filePath)) { throw new CategoryHelpFileNotFoundExeption(); } var data = TryDeserialize(File.ReadAllText(_filePath)); var categories = data .Where(kvp => IsSubjectOrOneLevelDeeper(kvp.Key)) .Select(kvp => new HelpInfo( kvp.Key.IndexOf(' ') > -1 ? kvp.Key.Substring(kvp.Key.IndexOf(' ') + 1) : kvp.Key, kvp.Key.Split(' ').FirstOrDefault(), kvp.Value, HelpInfoType.Category)) .ToList(); if (adjacencyCriteria.Equals(HelpAdjacencyCriteria.Empty())) { return(_defaultHelpInfo.WithChildren(categories)); } if (categories.Any(h => h.Subject == adjacencyCriteria.Subject)) { return(categories .First(h => h.Name == adjacencyCriteria.Subject) .WithChildren(categories.Where(h => h.Name != adjacencyCriteria.Subject))); } return(null); Dictionary <string, string> TryDeserialize(string json) { try { return(JsonConvert.DeserializeObject <Dictionary <string, string> >(json)); } catch { throw new CategoryHelpFileInvalidExeption(); } } bool IsSubjectOrOneLevelDeeper(string key) { var keySplit = key.Split(' '); var adjacencySplit = adjacencyCriteria.Subject .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (adjacencyCriteria.Subject == null && keySplit.Length == 1) { return(true); } return(key.StartsWith(adjacencyCriteria.Subject) && (keySplit.Length == adjacencySplit.Length || keySplit.Length == adjacencySplit.Length + 1)); } }