private static bool IsUsedBy( StructuralTypeConfiguration toCheckFor, IEdmTypeConfiguration toCheckIn, List<IEdmTypeConfiguration> typesChecked) { if (typesChecked.Contains(toCheckIn)) { return false; } typesChecked.Add(toCheckIn); if (toCheckIn == toCheckFor) { return true; } var toCheckInStructural = toCheckIn as StructuralTypeConfiguration; if (toCheckInStructural != null) { foreach (var property in toCheckInStructural.Properties .Where(p => !p.IsIgnored)) { var propertyType = toCheckFor.ModelBuilder.GetTypeConfigurationOrNull(property.RelatedClrType); if (IsUsedBy(toCheckFor, propertyType, typesChecked)) { return true; } } } typesChecked.Add(toCheckIn); return false; }
/// <summary> /// Constructs a CollectionPropertyConfiguration using the <paramref name="property">property</paramref> provided. /// </summary> public CollectionPropertyConfiguration(PropertyInfo property, StructuralTypeConfiguration declaringType) : base(property, declaringType) { if (!property.PropertyType.IsCollection(out _elementType)) { throw Error.Argument("property", SRResources.CollectionPropertiesMustReturnIEnumerable, property.Name, property.DeclaringType.FullName); } }
/// <summary> /// Initializes a new instance of the <see cref="PropertyConfiguration" /> class. /// </summary> /// <param name="property">The name of the property.</param> /// <param name="declaringType">The declaring EDM type of the property.</param> protected PropertyConfiguration(PropertyInfo property, StructuralTypeConfiguration declaringType) { if (property == null) { throw Error.ArgumentNull("property"); } if (declaringType == null) { throw Error.ArgumentNull("declaringType"); } PropertyInfo = property; DeclaringType = declaringType; AddedExplicitly = true; _name = property.Name; }
internal virtual void DerivesFromImpl(StructuralTypeConfiguration baseType) { if (baseType == null) { throw Error.ArgumentNull("baseType"); } _baseType = baseType; _baseTypeConfigured = true; if (!baseType.ClrType.IsAssignableFrom(ClrType) || baseType.ClrType == ClrType) { throw Error.Argument("baseType", SRResources.TypeDoesNotInheritFromBaseType, ClrType.FullName, baseType.ClrType.FullName); } foreach (PropertyConfiguration property in Properties) { ValidatePropertyNotAlreadyDefinedInBaseTypes(property.PropertyInfo); } foreach (PropertyConfiguration property in this.DerivedProperties()) { ValidatePropertyNotAlreadyDefinedInDerivedTypes(property.PropertyInfo); } }
internal virtual void DerivesFromNothingImpl() { _baseType = null; _baseTypeConfigured = true; }
/// <summary> /// Initializes a new instance of the <see cref="PrimitivePropertyConfiguration"/> class. /// </summary> /// <param name="property">The name of the property.</param> /// <param name="declaringType">The declaring EDM type of the property.</param> public PrimitivePropertyConfiguration(PropertyInfo property, StructuralTypeConfiguration declaringType) : base(property, declaringType) { }
/// <summary> /// Initializes a new instance of the <see cref="StructuralPropertyConfiguration"/> class. /// </summary> /// <param name="property">The property of the configuration.</param> /// <param name="declaringType">The declaring type of the property.</param> protected StructuralPropertyConfiguration(PropertyInfo property, StructuralTypeConfiguration declaringType) : base(property, declaringType) { OptionalProperty = EdmLibHelpers.IsNullable(property.PropertyType); }
// Returns all the derived types of this type. public static IEnumerable<StructuralTypeConfiguration> DerivedTypes(this ODataModelBuilder modelBuilder, StructuralTypeConfiguration structuralType) { if (modelBuilder == null) { throw Error.ArgumentNull("modelBuilder"); } if (structuralType == null) { throw Error.ArgumentNull("structuralType"); } if (structuralType.Kind == EdmTypeKind.Entity) { return DerivedTypes(modelBuilder, (EntityTypeConfiguration)structuralType); } if (structuralType.Kind == EdmTypeKind.Complex) { return DerivedTypes(modelBuilder, (ComplexTypeConfiguration)structuralType); } return Enumerable.Empty<StructuralTypeConfiguration>(); }
private void CreateStructuralTypeBody(EdmStructuredType type, StructuralTypeConfiguration config) { foreach (PropertyConfiguration property in config.Properties) { IEdmProperty edmProperty = null; switch (property.Kind) { case PropertyKind.Primitive: PrimitivePropertyConfiguration primitiveProperty = property as PrimitivePropertyConfiguration; if (primitiveProperty.IsIgnored) { continue; } EdmPrimitiveTypeKind typeKind = GetTypeKind(primitiveProperty.PropertyInfo.PropertyType); IEdmTypeReference primitiveTypeReference = EdmCoreModel.Instance.GetPrimitive( typeKind, primitiveProperty.OptionalProperty); // Set concurrency token if is entity type, and concurrency token is true EdmConcurrencyMode concurrencyMode = EdmConcurrencyMode.None; if (config.Kind == EdmTypeKind.Entity && primitiveProperty.ConcurrencyToken) { concurrencyMode = EdmConcurrencyMode.Fixed; } edmProperty = type.AddStructuralProperty( primitiveProperty.Name, primitiveTypeReference, defaultValue: null, concurrencyMode: concurrencyMode); break; case PropertyKind.Complex: ComplexPropertyConfiguration complexProperty = property as ComplexPropertyConfiguration; IEdmComplexType complexType = GetEdmType(complexProperty.RelatedClrType) as IEdmComplexType; edmProperty = type.AddStructuralProperty( complexProperty.Name, new EdmComplexTypeReference(complexType, complexProperty.OptionalProperty)); break; case PropertyKind.Collection: edmProperty = CreateStructuralTypeCollectionPropertyBody(type, (CollectionPropertyConfiguration)property); break; case PropertyKind.Enum: edmProperty = CreateStructuralTypeEnumPropertyBody(type, config, (EnumPropertyConfiguration)property); break; default: break; } if (edmProperty != null) { if (property.PropertyInfo != null) { _properties[property.PropertyInfo] = edmProperty; } if (property.IsRestricted) { _propertiesRestrictions[edmProperty] = new QueryableRestrictions(property); } } } }
// 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(_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>(_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 = 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 = 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. RemoveStructuralType(type.ClrType); } } }
internal bool InferEdmTypeFromDerivedTypes(Type propertyType, ref PropertyKind propertyKind) { HashSet <Type> visitedTypes = new HashSet <Type>(); Queue <Type> typeToBeVisited = new Queue <Type>(); typeToBeVisited.Enqueue(propertyType); IList <StructuralTypeConfiguration> foundMappedTypes = new List <StructuralTypeConfiguration>(); while (typeToBeVisited.Count != 0) { Type currentType = typeToBeVisited.Dequeue(); visitedTypes.Add(currentType); List <Type> derivedTypes; if (_allTypesWithDerivedTypeMapping.Value.TryGetValue(currentType, out derivedTypes)) { foreach (Type derivedType in derivedTypes) { if (!visitedTypes.Contains(derivedType)) { StructuralTypeConfiguration structuralType = _explicitlyAddedTypes.FirstOrDefault(c => c.ClrType == derivedType); if (structuralType != null) { foundMappedTypes.Add(structuralType); } typeToBeVisited.Enqueue(derivedType); } } } } if (!foundMappedTypes.Any()) { return(false); } IEnumerable <EntityTypeConfiguration> foundMappedEntityType = foundMappedTypes.OfType <EntityTypeConfiguration>().ToList(); IEnumerable <ComplexTypeConfiguration> foundMappedComplexType = foundMappedTypes.OfType <ComplexTypeConfiguration>().ToList(); if (!foundMappedEntityType.Any()) { propertyKind = PropertyKind.Complex; return(true); } else if (!foundMappedComplexType.Any()) { propertyKind = PropertyKind.Navigation; return(true); } else { throw Error.InvalidOperation(SRResources.CannotInferEdmType, propertyType.FullName, String.Join(",", foundMappedEntityType.Select(e => e.ClrType.FullName)), String.Join(",", foundMappedComplexType.Select(e => e.ClrType.FullName))); } }
private void MapStructuralProperty(StructuralTypeConfiguration type, PropertyInfo property, PropertyKind propertyKind, bool isCollection) { Contract.Assert(type != null); Contract.Assert(property != null); Contract.Assert(propertyKind == PropertyKind.Complex || propertyKind == PropertyKind.Primitive || propertyKind == PropertyKind.Enum); bool addedExplicitly = type.Properties.Any(p => p.PropertyInfo.Name == property.Name); PropertyConfiguration addedEdmProperty; if (!isCollection) { if (propertyKind == PropertyKind.Primitive) { addedEdmProperty = type.AddPrimitiveProperty(property); } else if (propertyKind == PropertyKind.Enum) { AddEnumType(TypeHelper.GetUnderlyingTypeOrSelf(property.PropertyType)); addedEdmProperty = type.AddEnumProperty(property); } else { addedEdmProperty = type.AddComplexProperty(property); } } else { if (_isQueryCompositionMode) { Contract.Assert(propertyKind != PropertyKind.Complex, "we don't create complex types in query composition mode."); } if (property.PropertyType.GetTypeInfo().IsGenericType) { Type elementType = property.PropertyType.GetGenericArguments().First(); Type elementUnderlyingTypeOrSelf = TypeHelper.GetUnderlyingTypeOrSelf(elementType); if (elementUnderlyingTypeOrSelf.GetTypeInfo().IsEnum) { AddEnumType(elementUnderlyingTypeOrSelf); } } else { Type elementType; if (property.PropertyType.IsCollection(out elementType)) { Type elementUnderlyingTypeOrSelf = TypeHelper.GetUnderlyingTypeOrSelf(elementType); if (elementUnderlyingTypeOrSelf.GetTypeInfo().IsEnum) { AddEnumType(elementUnderlyingTypeOrSelf); } } } addedEdmProperty = type.AddCollectionProperty(property); } addedEdmProperty.AddedExplicitly = addedExplicitly; }
private void ApplyPropertyConvention(IEdmPropertyConvention propertyConvention, StructuralTypeConfiguration edmTypeConfiguration) { Contract.Assert(propertyConvention != null); Contract.Assert(edmTypeConfiguration != null); foreach (PropertyConfiguration property in edmTypeConfiguration.Properties.ToArray()) { propertyConvention.Apply(property, edmTypeConfiguration, this); } }
/// <summary> /// Instantiates a new instance of the <see cref="ComplexPropertyConfiguration"/> class. /// </summary> /// <param name="property">The property of the configuration.</param> /// <param name="declaringType">The declaring type of the property.</param> public ComplexPropertyConfiguration(PropertyInfo property, StructuralTypeConfiguration declaringType) : base(property, declaringType) { }
// Returns the base types, this type and all the derived types of this type. public static IEnumerable<StructuralTypeConfiguration> ThisAndBaseAndDerivedTypes( this ODataModelBuilder modelBuilder, StructuralTypeConfiguration structuralType) { Contract.Assert(modelBuilder != null); Contract.Assert(structuralType != null); return structuralType.BaseTypes() .Concat(new[] { structuralType }) .Concat(modelBuilder.DerivedTypes(structuralType)); }
private IEdmProperty CreateStructuralTypeEnumPropertyBody(EdmStructuredType type, StructuralTypeConfiguration config, EnumPropertyConfiguration enumProperty) { Type enumPropertyType = TypeHelper.GetUnderlyingTypeOrSelf(enumProperty.RelatedClrType); IEdmType edmType = GetEdmType(enumPropertyType); if (edmType == null) { throw Error.InvalidOperation(SRResources.EnumTypeDoesNotExist, enumPropertyType.Name); } IEdmEnumType enumType = (IEdmEnumType)edmType; IEdmTypeReference enumTypeReference = new EdmEnumTypeReference(enumType, enumProperty.OptionalProperty); // Set concurrency token if is entity type, and concurrency token is true EdmConcurrencyMode enumConcurrencyMode = EdmConcurrencyMode.None; if (config.Kind == EdmTypeKind.Entity && enumProperty.ConcurrencyToken) { enumConcurrencyMode = EdmConcurrencyMode.Fixed; } return type.AddStructuralProperty( enumProperty.Name, enumTypeReference, defaultValue: null, concurrencyMode: enumConcurrencyMode); }
public static bool IsAssignableFrom(this StructuralTypeConfiguration baseStructuralType, StructuralTypeConfiguration structuralType) { if (structuralType.Kind == EdmTypeKind.Entity && baseStructuralType.Kind == EdmTypeKind.Entity) { EntityTypeConfiguration entity = (EntityTypeConfiguration)structuralType; while (entity != null) { if (baseStructuralType == entity) { return true; } entity = entity.BaseType; } } else if (structuralType.Kind == EdmTypeKind.Complex && baseStructuralType.Kind == EdmTypeKind.Complex) { ComplexTypeConfiguration complex = (ComplexTypeConfiguration)structuralType; while (complex != null) { if (baseStructuralType == complex) { return true; } complex = complex.BaseType; } } return false; }
/// <summary> /// Initializes a new instance of the <see cref="BindingPathConfiguration{TStructuralType}"/> class. /// </summary> /// <param name="modelBuilder">The model builder.</param> /// <param name="structuralType">The type configuration.</param> /// <param name="navigationSource">The navigation source configuration.</param> public BindingPathConfiguration(ODataModelBuilder modelBuilder, StructuralTypeConfiguration <TStructuralType> structuralType, NavigationSourceConfiguration navigationSource) : this(modelBuilder, structuralType, navigationSource, new List <object>()) { }