/// <summary> /// Parses a term key string and returns a term describing it. All terms are created here. /// The main caller is TypeCache.MakeTerm, but it's also called from places that use a /// dynamic domain (processors). /// </summary> public Term Parse(Type resource, string key, string componentSeparator, TermBindingRule bindingRule, ICollection <string> dynDomain) { var term = new Term(componentSeparator); Property propertyMaker(string str) { if (string.IsNullOrWhiteSpace(str)) { throw new InvalidSyntax(ErrorCodes.InvalidConditionSyntax, $"Invalid condition '{str}'"); } if (dynDomain?.Contains(str, StringComparer.OrdinalIgnoreCase) == true) { return(DynamicProperty.Parse(str)); } Property make(Type type) { switch (bindingRule) { case TermBindingRule.DeclaredWithDynamicFallback: try { return(TypeCache.FindDeclaredProperty(type, str)); } catch (UnknownProperty) { return(DynamicProperty.Parse(str)); } case TermBindingRule.DynamicWithDeclaredFallback: return(DynamicProperty.Parse(str, true)); case TermBindingRule.OnlyDeclared: try { return(TypeCache.FindDeclaredProperty(type, str)); } catch (UnknownProperty) { if (type.GetSubclasses().Any(subClass => TypeCache.TryFindDeclaredProperty(subClass, str, out _))) { return(DynamicProperty.Parse(str)); } throw; } default: throw new Exception(); } } return(term.LastOrDefault() switch { null => make(resource), DeclaredProperty declared => make(declared.Type), _ => DynamicProperty.Parse(str) }); }
/// <summary> /// Converts all properties in this term to dynamic properties /// </summary> private static Term MakeDynamic(Term term) { if (term.IsDynamic) { return(term); } var newTerm = new Term(term.ComponentSeparator); newTerm.Store.AddRange(term.Store.Select(prop => prop switch { DynamicProperty _ => prop, DeclaredProperty _ => DynamicProperty.Parse(prop.Name), _ => throw new ArgumentOutOfRangeException() }));