/// <summary> /// Resolves the specified entity model structured type and returns the Edm model type for it. /// </summary> /// <param name="model">The model to get the type from.</param> /// <param name="structuredType">The entity model structured type to resolve.</param> /// <returns>The resolved type for the specified <paramref name="structuredType"/>.</returns> public static IEdmStructuredType ResolveEntityModelSchemaStructuredType(IEdmModel model, NamedStructuralType structuredType) { DataType owningDataType = null; EntityType owningEntityType = structuredType as EntityType; if (owningEntityType != null) { owningDataType = DataTypes.EntityType.WithDefinition(owningEntityType); } ComplexType owningComplexType = structuredType as ComplexType; if (owningComplexType != null) { owningDataType = DataTypes.ComplexType.WithDefinition(owningComplexType); } if (owningDataType == null) { return null; } IEdmStructuredTypeReference structuredTypeReference = EdmModelUtils.ResolveEntityModelSchemaType(model, owningDataType) as IEdmStructuredTypeReference; return structuredTypeReference == null ? null : structuredTypeReference.StructuredDefinition(); }
/// <summary> /// Creates metadata properties for the specified enumeration of OData OM properties. /// </summary> /// <param name="model">The model to use.</param> /// <param name="owningType">The owning type to which to add the properties.</param> /// <param name="properties">Enumeration of the properties to add.</param> private static void CreateMetadataProperties(EntityModelSchema model, NamedStructuralType owningType, IEnumerable<ODataProperty> properties) { if (properties == null) { return; } foreach (ODataProperty property in properties) { ODataPropertyMetadataAnnotation propertyMetadataAnnotation = property.GetInheritedAnnotation<ODataPropertyMetadataAnnotation>(); object propertyValue = property.Value; bool isOpenProperty = false; if (propertyMetadataAnnotation != null) { isOpenProperty = propertyMetadataAnnotation.IsOpenProperty; ExceptionUtilities.Assert( !isOpenProperty || owningType is EntityType, "Can't declare an open property on non-entity type."); if (propertyMetadataAnnotation.PropertyValueForTypeInference != null) { propertyValue = propertyMetadataAnnotation.PropertyValueForTypeInference; } } ODataComplexValue complexValue = propertyValue as ODataComplexValue; if (complexValue != null) { ExceptionUtilities.Assert(complexValue.TypeName.StartsWith(owningType.NamespaceName + "."), "The type name must start with the same namespace as its owning type."); ComplexType complexType = model.GetComplexType(complexValue.TypeName); if (complexType == null) { string complexTypeLocalName = complexValue.TypeName.Substring(owningType.NamespaceName.Length + 1); complexType = model.ComplexType(complexTypeLocalName, owningType.NamespaceName); CreateMetadataProperties(model, complexType, complexValue.Properties); } if (isOpenProperty) { owningType.IsOpen = true; } else { owningType.Property(property.Name, DataTypes.ComplexType.WithDefinition(complexType).Nullable()); } } else { bool isKeyProperty = false; bool isETagProperty = false; if (propertyMetadataAnnotation != null) { isKeyProperty = (propertyMetadataAnnotation.Kind & ODataPropertyKind.Key) == ODataPropertyKind.Key; isETagProperty = (propertyMetadataAnnotation.Kind & ODataPropertyKind.ETag) == ODataPropertyKind.ETag; ExceptionUtilities.Assert( !isKeyProperty || owningType is EntityType, "Can't declare a key property on non-entity type."); ExceptionUtilities.Assert( !isETagProperty || owningType is EntityType, "Can't declare an etag property on non-entity type."); ExceptionUtilities.Assert( !isOpenProperty || !(isKeyProperty || isETagProperty), "Key or etag property can't be open."); } if (owningType is EntityType && isOpenProperty) { owningType.IsOpen = true; } else { EntityType owningEntityType = owningType as EntityType; if (owningEntityType != null && isKeyProperty) { ExceptionUtilities.Assert( propertyValue != null, "Found a key property with null value, can't infer type from value in that case and it's invalid anyway."); PrimitiveDataType keyPropertyType = EntityModelUtils.GetPrimitiveEdmType(propertyValue.GetType()); owningEntityType.KeyProperty(property.Name, keyPropertyType, isETagProperty); } else { if (propertyValue is ODataCollectionValue) { string itemTypeName = EntityModelUtils.GetCollectionItemTypeName(((ODataCollectionValue)propertyValue).TypeName); CollectionDataType collectionType = null; DataType primitiveItemType = EntityModelUtils.GetPrimitiveEdmType(itemTypeName); if (primitiveItemType != null) { collectionType = DataTypes.CollectionType.WithElementDataType(primitiveItemType); } else { ComplexType complexItemType = model.GetComplexType(itemTypeName); collectionType = DataTypes.CollectionOfComplex(complexItemType); } ExceptionUtilities.Assert(collectionType != null, "Could not resolve item type."); owningType.Property(property.Name, collectionType); } else { Type propertyType = propertyValue == null ? typeof(string) : propertyValue.GetType(); PrimitiveDataType edmPropertyType = EntityModelUtils.GetPrimitiveEdmType(propertyType); owningType.Property(property.Name, edmPropertyType, isETagProperty); } } } } } }
/// <summary> /// Compares the member properties. /// </summary> /// <param name="expectedType">The expected type.</param> /// <param name="expectedProperties">The expected properties.</param> /// <param name="actualProperties">The actual properties.</param> protected virtual void CompareMemberProperties(NamedStructuralType expectedType, IEnumerable<MemberProperty> expectedProperties, IEnumerable<MemberProperty> actualProperties) { foreach (MemberProperty expectedProperty in expectedProperties) { List<MemberProperty> members = actualProperties.Where(p => p.Name == expectedProperty.Name).ToList(); if (!this.WriteErrorIfFalse(members.Count == 1, "Cannot find member '{0}' on type '{1}'", expectedProperty.Name, expectedType.FullName)) { MemberProperty actualProperty = members.Single(); this.CompareMemberProperty(expectedProperty, actualProperty); } } }
private CodeTypeReference GetClrTypeReference(NamedStructuralType type) { if (type.IsTypeBacked()) { return Code.TypeRef(type.FullName); } else { return Code.TypeRef(DefaultInstanceTypeName); } }
private static void Fixup(NamedStructuralType structuralType, List<NamedStructuralType> visited) { if (visited.Contains(structuralType)) { return; } visited.Add(structuralType); foreach (MemberProperty property in structuralType.Properties) { PrimitiveDataType primitiveDataType = property.PropertyType as PrimitiveDataType; ComplexDataType complexDataType = property.PropertyType as ComplexDataType; if (complexDataType != null) { Fixup(complexDataType.Definition, visited); } else if (primitiveDataType != null) { Type clrType = primitiveDataType.GetFacetValue<PrimitiveClrTypeFacet, Type>(null); ExceptionUtilities.CheckObjectNotNull(clrType, "PrimitiveClrTypeFacet has not been defined for the property: '{0}.{1}'.", structuralType.Name, property.Name); AddDataGenerationHints(property, clrType); property.PropertyType = FixupType(primitiveDataType, clrType); } } }
private void CompareProperties(NamedStructuralType expectedStructuralType, NamedStructuralType actualStructuralType) { // TODO: for open type, actual can have more properties this.SatisfiesEquals( expectedStructuralType.Properties.Count(), actualStructuralType.Properties.Count(), "Count of Properties of '{0}' does not match.", expectedStructuralType.FullName); foreach (MemberProperty memberProperty in expectedStructuralType.Properties) { var actualMemberProperties = actualStructuralType.Properties.Where(p => p.Name == memberProperty.Name); if (this.SatisfiesEquals(1, actualMemberProperties.Count(), "Should find exactly one member '{0}'.", memberProperty.Name)) { var actualMemberProperty = actualMemberProperties.Single(); this.CompareMemberProperty(memberProperty, actualMemberProperty); this.CompareAnnotations(memberProperty.Annotations, actualMemberProperty.Annotations); } } }
private void CompareStructuralType(NamedStructuralType expected, NamedStructuralType actual) { var expectedEntityType = expected as EntityType; if (expectedEntityType != null) { this.CompareEntityType(expectedEntityType, (EntityType)actual); } else { this.CompareComplexType((ComplexType)expected, (ComplexType)actual); } }
private void ParseNamedStructuralTypeAttributes(XElement typeElement, NamedStructuralType type) { type.IsAbstract = XmlConvert.ToBoolean(typeElement.GetOptionalAttributeValue("Abstract", "false")); type.IsOpen = XmlConvert.ToBoolean(typeElement.GetOptionalAttributeValue("OpenType", "false")); string baseTypeFullName = typeElement.GetOptionalAttributeValue("BaseType", null); if (baseTypeFullName != null) { string[] typeNameInfo = this.ParseEdmTypeName(baseTypeFullName); string baseTypeNamespace = typeNameInfo[0]; string baseTypeName = typeNameInfo[1]; ComplexType complexType = type as ComplexType; EntityType entityType = type as EntityType; if (complexType != null) { complexType.BaseType = new ComplexTypeReference(baseTypeNamespace, baseTypeName); } else { ExceptionUtilities.Assert(entityType != null, "{0} is neither Entity nor Complex, but {1}!", type.FullName, type.GetType()); entityType.BaseType = new EntityTypeReference(baseTypeNamespace, baseTypeName); } } string typeaccess = typeElement.GetOptionalAttributeValue(EdmConstants.CodegenNamespace + "TypeAccess", null); if (typeaccess != null) { type.Annotations.Add(new TypeAccessModifierAnnotation(this.GetAccessModifier(typeaccess))); } }
/// <summary> /// Build a Type reference for a structural type /// </summary> /// <param name="structuralType">Structural Type</param> /// <returns>Code Type Reference</returns> public override CodeTypeReference ResolveClrTypeReference(NamedStructuralType structuralType) { return Code.TypeRef(structuralType.FullName); }