public void HasManyPath_AddBindindPath_Derived(bool contained)
        {
            // Assert
            ODataModelBuilder builder = new ODataModelBuilder();
            var customerType          = builder.EntityType <BindingCustomer>();
            var navigationSource      = builder.EntitySet <BindingCustomer>("Customers");

            StructuralTypeConfiguration addressType = builder.StructuralTypes.FirstOrDefault(c => c.Name == "BindingAddress");

            Assert.Null(addressType);              // Guard
            Assert.Empty(customerType.Properties); // Guard

            // Act
            var binding    = new BindingPathConfiguration <BindingCustomer>(builder, customerType, navigationSource.Configuration);
            var newBinding = binding.HasManyPath((BindingVipCustomer v) => v.VipAddresses, contained);

            // Assert
            addressType = builder.StructuralTypes.FirstOrDefault(c => c.Name == "BindingAddress");
            Assert.NotNull(addressType);
            Assert.Empty(customerType.Properties);

            StructuralTypeConfiguration vipCustomerType = builder.StructuralTypes.FirstOrDefault(c => c.Name == "BindingVipCustomer");

            Assert.NotNull(vipCustomerType);
            var vipAddressesProperty = Assert.Single(vipCustomerType.Properties);

            Assert.Equal("VipAddresses", vipAddressesProperty.Name);

            if (contained)
            {
                Assert.Equal(EdmTypeKind.Entity, addressType.Kind);
                Assert.Equal(PropertyKind.Navigation, vipAddressesProperty.Kind);
                NavigationPropertyConfiguration navigationProperty = Assert.IsType <NavigationPropertyConfiguration>(vipAddressesProperty);
                Assert.Equal(EdmMultiplicity.Many, navigationProperty.Multiplicity);
                Assert.True(navigationProperty.ContainsTarget);
            }
            else
            {
                Assert.Equal(EdmTypeKind.Complex, addressType.Kind);
                Assert.Equal(PropertyKind.Collection, vipAddressesProperty.Kind);
                CollectionPropertyConfiguration collection = Assert.IsType <CollectionPropertyConfiguration>(vipAddressesProperty);
                Assert.Equal(typeof(BindingAddress), collection.ElementType);
            }

            // different bindings
            Assert.NotSame(binding, newBinding);
            Assert.Equal("", binding.BindingPath);

            Assert.IsType <BindingPathConfiguration <BindingAddress> >(newBinding);
            Assert.Equal("Microsoft.AspNet.OData.Test.Formatter.BindingVipCustomer/VipAddresses", newBinding.BindingPath);
        }
示例#2
0
        private IEdmProperty CreateStructuralTypeCollectionPropertyBody(EdmStructuredType type, CollectionPropertyConfiguration collectionProperty)
        {
            IEdmTypeReference elementTypeReference = null;
            Type clrType = TypeHelper.GetUnderlyingTypeOrSelf(collectionProperty.ElementType);

            if (TypeHelper.IsEnum(clrType))
            {
                IEdmType edmType = GetEdmType(clrType);

                if (edmType == null)
                {
                    throw Error.InvalidOperation(SRResources.EnumTypeDoesNotExist, clrType.Name);
                }

                IEdmEnumType enumElementType = (IEdmEnumType)edmType;
                bool         isNullable      = collectionProperty.ElementType != clrType;
                elementTypeReference = new EdmEnumTypeReference(enumElementType, isNullable);
            }
            else
            {
                IEdmType edmType = GetEdmType(collectionProperty.ElementType);
                if (edmType != null)
                {
                    IEdmComplexType elementType = edmType as IEdmComplexType;
                    Contract.Assert(elementType != null);
                    elementTypeReference = new EdmComplexTypeReference(elementType, collectionProperty.NullableProperty);
                }
                else
                {
                    elementTypeReference =
                        EdmLibHelpers.GetEdmPrimitiveTypeReferenceOrNull(collectionProperty.ElementType);
                    Contract.Assert(elementTypeReference != null);
                }
            }

            return(type.AddStructuralProperty(
                       collectionProperty.Name,
                       new EdmCollectionTypeReference(new EdmCollectionType(elementTypeReference))));
        }
        // the convention model builder MapTypes() method might have went through deep object graphs and added a bunch of types
        // only to realise after applying the conventions that the user has ignored some of the properties. So, prune the unreachable stuff.
        private void PruneUnreachableTypes()
        {
            Contract.Assert(this._explicitlyAddedTypes != null);

            // Do a BFS starting with the types the user has explicitly added to find out the unreachable nodes.
            Queue <StructuralTypeConfiguration>   reachableTypes = new Queue <StructuralTypeConfiguration>(this._explicitlyAddedTypes);
            HashSet <StructuralTypeConfiguration> visitedTypes   = new HashSet <StructuralTypeConfiguration>();

            while (reachableTypes.Count != 0)
            {
                StructuralTypeConfiguration currentType = reachableTypes.Dequeue();

                // go visit other end of each of this node's edges.
                foreach (PropertyConfiguration property in currentType.Properties.Where(property => property.Kind != PropertyKind.Primitive))
                {
                    if (property.Kind == PropertyKind.Collection)
                    {
                        // if the elementType is primitive we don't need to do anything.
                        CollectionPropertyConfiguration colProperty = property as CollectionPropertyConfiguration;
                        if (EdmLibHelpers.GetEdmPrimitiveTypeOrNull(colProperty.ElementType) != null)
                        {
                            continue;
                        }
                    }

                    IEdmTypeConfiguration propertyType = this.GetStructuralTypeOrNull(property.RelatedClrType);
                    Contract.Assert(propertyType != null, "we should already have seen this type");

                    var structuralTypeConfiguration = propertyType as StructuralTypeConfiguration;
                    if (structuralTypeConfiguration != null && !visitedTypes.Contains(propertyType))
                    {
                        reachableTypes.Enqueue(structuralTypeConfiguration);
                    }
                }

                // all derived types and the base type are also reachable
                if (currentType.Kind == EdmTypeKind.Entity)
                {
                    EntityTypeConfiguration currentEntityType = (EntityTypeConfiguration)currentType;
                    if (currentEntityType.BaseType != null && !visitedTypes.Contains(currentEntityType.BaseType))
                    {
                        reachableTypes.Enqueue(currentEntityType.BaseType);
                    }

                    foreach (EntityTypeConfiguration derivedType in this.DerivedTypes(currentEntityType))
                    {
                        if (!visitedTypes.Contains(derivedType))
                        {
                            reachableTypes.Enqueue(derivedType);
                        }
                    }
                }
                else if (currentType.Kind == EdmTypeKind.Complex)
                {
                    ComplexTypeConfiguration currentComplexType = (ComplexTypeConfiguration)currentType;
                    if (currentComplexType.BaseType != null && !visitedTypes.Contains(currentComplexType.BaseType))
                    {
                        reachableTypes.Enqueue(currentComplexType.BaseType);
                    }

                    foreach (ComplexTypeConfiguration derivedType in this.DerivedTypes(currentComplexType))
                    {
                        if (!visitedTypes.Contains(derivedType))
                        {
                            reachableTypes.Enqueue(derivedType);
                        }
                    }
                }

                visitedTypes.Add(currentType);
            }

            StructuralTypeConfiguration[] allConfiguredTypes = this.StructuralTypes.ToArray();
            foreach (StructuralTypeConfiguration type in allConfiguredTypes)
            {
                if (!visitedTypes.Contains(type))
                {
                    // we don't have to fix up any properties because this type is unreachable and cannot be a property of any reachable type.
                    this.RemoveStructuralType(type.ClrType);
                }
            }
        }