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); }