/// <summary> /// Filter rules by <paramref name="filterCriteria"/>. /// </summary> /// <param name="filterCriteria"></param> /// <returns><see cref="PluralRulesCasesEvaluatable"/> or <see cref="PluralRulesArray"/>, or null if content is empty</returns> public IPluralRulesEnumerable Query(PluralRuleInfo filterCriteria) { // Try get IPluralRulesEnumerable result = null; lock (m_lock) if (queries.TryGetValue(filterCriteria, out result)) { return(result); } // Query if (ruleSource is IPluralRulesQueryable queryable) { result = queryable.Query(filterCriteria); // Wrap into PluralRulesEvaluatable if (result != null && filterCriteria.Category != null && filterCriteria.Culture != null && filterCriteria.Case == null && filterCriteria.Optional == -1) { result = new PluralRulesCasesEvaluatable(result); } } else if (ruleSource is IEnumerable <IPluralRule> enumr) { // Filter rules StructList8 <IPluralRule> list = new StructList8 <IPluralRule>(); StructList8 <string> rulesets = new StructList8 <string>(); foreach (IPluralRule rule in enumr) { // Filter by criteria if (!filterCriteria.FilterMatch(rule.Info)) { continue; } // Gather a list of rulesets if (rule.Info.RuleSet != null && !rulesets.Contains(rule.Info.RuleSet)) { rulesets.Add(rule.Info.RuleSet); } // Add to list list.Add(rule); } // No result if (list.Count == 0) { result = null; } // Instantiate PluralRulesEvaluatable else if (rulesets.Count <= 1 && filterCriteria.Category != null && filterCriteria.Culture != null && filterCriteria.Case == null && filterCriteria.Optional == -1) { result = new PluralRulesCasesEvaluatable(list.ToArray()); } // Instantiate PluralRules. else { result = new PluralRulesArray(list.ToArray()); } } // Could not read source else { result = null; } // Write to cache, if is still new lock (m_lock) if (!queries.ContainsKey(filterCriteria)) { queries[filterCriteria] = result; } // Return result return(result); }
/// <summary> /// Create plural rules resolver /// </summary> /// <param name="assemblyLoader">(optional) function that reads assembly from file.</param> /// <param name="typeResolver">(optional) Function that resolves type name into <see cref="Type"/>.</param> /// <param name="ruleExpressionParser">(optional) rule parser. If null, will not parser expressions.</param> /// <param name="rulesFactory">(optional) Function that converts enumerable to <see cref="IPluralRules"/></param> public PluralRulesResolver(Func <AssemblyName, Assembly> assemblyLoader, Func <Assembly, string, bool, Type> typeResolver, Func <string, IEnumerable <IPluralRule> > ruleExpressionParser, Func <IEnumerable <IPluralRule>, IPluralRulesEnumerable> rulesFactory) { this.assemblyResolver = assemblyLoader; this.typeResolver = typeResolver; this.ruleExpressionParser = ruleExpressionParser; this.rulesFactory = rulesFactory; this.resolveFunc = (string rules) => { try { // Empty if (String.IsNullOrEmpty(rules)) { return new ResultLine { Rules = null, Error = null } } ; // Enumerable IEnumerable <IPluralRule> enumr = null; // Parse Expression if (rules[0] == '[') { // Assert ruleExpressionParser is not null if (ruleExpressionParser == null) { throw new InvalidOperationException($"{nameof(ruleExpressionParser)} is null"); } // Create parse enumr = this.ruleExpressionParser(rules); } else // Resolve class { enumr = ResolveRulesClass(rules); } // No result if (enumr == null) { return new ResultLine { Error = null, Rules = null } } ; // Cast IPluralRulesEnumerable rulesEnumr = rulesFactory(enumr); // Result return(new ResultLine { Rules = rulesEnumr }); } catch (Exception e) { return(new ResultLine { Error = e }); } }; }