/// <summary> /// Finds rules for the specified property on an object contained in the specified "child property". /// </summary> /// <param name="property">The property to find the rules for.</param> /// <param name="propertiesToFind">Paths to the specified property in relation to already found rules.</param> /// <param name="processed">Types that are already processed and should be ignores.</param> /// <param name="modelPath">The base path to the model.</param> /// <param name="deferredRules">Rules that were found on non-matching types.</param> /// <param name="childProperty">A property that might contain a child object that has the property for which the rules should be found.</param> /// <param name="pathPrefix">The current property model path.</param> /// <returns></returns> private static IEnumerable <DryvRuleNode> FindRulesForPropertyInChild(PropertyInfo property, IList <RulePaths> propertiesToFind, ISet <Type> processed, string modelPath, ConcurrentDictionary <Type, List <DryvRuleDefinition> > deferredRules, PropertyInfo childProperty, string pathPrefix) { var childType = childProperty.GetElementType(); var childPropertyName = childProperty.Name.ToCamelCase(); var pathToChildProperty = $"{pathPrefix}{childPropertyName}"; propertiesToFind = AdvancePathForCurrentProperty(propertiesToFind, childPropertyName); foreach (var node in GetRulesAtCurrentPath(propertiesToFind, modelPath, pathToChildProperty)) { yield return(node); } propertiesToFind = RemoveRulesAtCurrentPath(propertiesToFind); if (!childProperty.IsNavigationProperty() || pathToChildProperty.StartsWith(modelPath) && pathToChildProperty != modelPath && processed.Contains(childProperty.PropertyType) && !propertiesToFind.Any()) { yield break; } foreach (var node in childType.FindRulesForProperty( property, propertiesToFind, processed, pathToChildProperty, modelPath, deferredRules.Clone())) { yield return(node); } }