private static void FindNavigationProperties(this ODataModelBuilder builder, StructuralTypeConfiguration configuration,
                                                     IList <Tuple <StructuralTypeConfiguration, IList <MemberInfo>, NavigationPropertyConfiguration> > navs,
                                                     Stack <MemberInfo> path, HashSet <Type> typesAlreadyProcessed)
        {
            Contract.Assert(builder != null);
            Contract.Assert(configuration != null);
            Contract.Assert(navs != null);
            Contract.Assert(path != null);

            foreach (var property in configuration.Properties)
            {
                path.Push(property.PropertyInfo);

                NavigationPropertyConfiguration nav        = property as NavigationPropertyConfiguration;
                ComplexPropertyConfiguration    complex    = property as ComplexPropertyConfiguration;
                CollectionPropertyConfiguration collection = property as CollectionPropertyConfiguration;

                if (nav != null)
                {
                    // how about the containment?
                    IList <MemberInfo> bindingPath = path.Reverse().ToList();

                    navs.Add(
                        new Tuple <StructuralTypeConfiguration, IList <MemberInfo>, NavigationPropertyConfiguration>(configuration,
                                                                                                                     bindingPath, nav));
                }
                else if (complex != null && !typesAlreadyProcessed.Contains(complex.RelatedClrType))
                {
                    StructuralTypeConfiguration complexType = builder.GetTypeConfigurationOrNull(complex.RelatedClrType) as StructuralTypeConfiguration;

                    // Prevent infinite recursion on self-referential complex types.
                    typesAlreadyProcessed.Add(complex.RelatedClrType);
                    builder.FindAllNavigationPropertiesRecursive(complexType, navs, path, typesAlreadyProcessed);
                    typesAlreadyProcessed.Remove(complex.RelatedClrType);
                }
                else if (collection != null && !typesAlreadyProcessed.Contains(collection.ElementType))
                {
                    IEdmTypeConfiguration edmType = builder.GetTypeConfigurationOrNull(collection.ElementType);
                    if (edmType != null && edmType.Kind == EdmTypeKind.Complex)
                    {
                        StructuralTypeConfiguration complexType = (StructuralTypeConfiguration)edmType;

                        // Prevent infinite recursion on self-referential complex types.
                        typesAlreadyProcessed.Add(collection.ElementType);
                        builder.FindAllNavigationPropertiesRecursive(complexType, navs, path, typesAlreadyProcessed);
                        typesAlreadyProcessed.Remove(collection.ElementType);
                    }
                }

                path.Pop();
            }
        }
        /// <summary>
        /// Adds a complex property to this edm type.
        /// </summary>
        /// <param name="propertyInfo">The property being added.</param>
        /// <returns>The <see cref="ComplexPropertyConfiguration"/> so that the property can be configured further.</returns>
        public virtual ComplexPropertyConfiguration AddComplexProperty(PropertyInfo propertyInfo)
        {
            if (propertyInfo == null)
            {
                throw Error.ArgumentNull("propertyInfo");
            }

            if (!TypeHelper.GetReflectedType(propertyInfo).IsAssignableFrom(ClrType))
            {
                throw Error.Argument("propertyInfo", SRResources.PropertyDoesNotBelongToType, propertyInfo.Name, ClrType.FullName);
            }

            ValidatePropertyNotAlreadyDefinedInBaseTypes(propertyInfo);
            ValidatePropertyNotAlreadyDefinedInDerivedTypes(propertyInfo);

            // Remove from the ignored properties
            if (RemovedProperties.Any(prop => prop.Name.Equals(propertyInfo.Name, StringComparison.Ordinal)))
            {
                RemovedProperties.Remove(RemovedProperties.First(prop => prop.Name.Equals(propertyInfo.Name, StringComparison.Ordinal)));
            }

            ComplexPropertyConfiguration propertyConfiguration =
                ValidatePropertyNotAlreadyDefinedOtherTypes <ComplexPropertyConfiguration>(propertyInfo,
                                                                                           SRResources.MustBeComplexProperty);

            if (propertyConfiguration == null)
            {
                propertyConfiguration            = new ComplexPropertyConfiguration(propertyInfo, this);
                ExplicitProperties[propertyInfo] = propertyConfiguration;
                // Make sure the complex type is in the model.

                ModelBuilder.AddComplexType(propertyInfo.PropertyType);
            }

            return(propertyConfiguration);
        }