/// <summary> /// Map the given property name. /// </summary> /// <param name="propertyName">The given property name.</param> /// <returns>The mapped property name.</returns> public string MapProperty(string propertyName) { if (string.IsNullOrEmpty(propertyName)) { throw new ArgumentNullException(nameof(propertyName)); } IEdmProperty property = _type.Properties().Single(s => s.Name == propertyName); PropertyInfo info = GetPropertyInfo(property); JsonPropertyAttribute jsonProperty = GetJsonProperty(info); if (jsonProperty != null && !string.IsNullOrWhiteSpace(jsonProperty.PropertyName)) { return(jsonProperty.PropertyName); } else { return(property.Name); } }
/// <summary> /// Resolve property from property name /// </summary> /// <param name="type">The declaring type.</param> /// <param name="propertyName">The property name.</param> /// <returns>The resolved <see cref="IEdmProperty"/></returns> public virtual IEdmProperty ResolveProperty(IEdmStructuredType type, string propertyName) { if (EnableCaseInsensitive) { var result = type.Properties() .Where(_ => string.Equals(propertyName, _.Name, StringComparison.OrdinalIgnoreCase)) .ToList(); if (result.Count == 1) { return(result.Single()); } else if (result.Count > 1) { throw new ODataException(Strings.UriParserMetadata_MultipleMatchingPropertiesFound(propertyName, type.ODataFullName())); } } return(type.FindProperty(propertyName)); }
public static TPropertyType AssertHasProperty <TPropertyType>(this IEdmStructuredType edmType, IEdmModel model, string propertyName, string propertyType, bool isNullable) where TPropertyType : IEdmProperty { IEnumerable <TPropertyType> properties = edmType .Properties() .OfType <TPropertyType>() .Where(p => p.Name == propertyName); Assert.True(properties.Count() == 1); TPropertyType property = properties.Single(); if (propertyType != null) { Assert.True(property.Type.Definition.IsEquivalentTo(model.FindType(propertyType))); } Assert.Equal(isNullable, property.Type.IsNullable); return(property); }
private static IOpenApiAny CreateStructuredTypePropertiesExample(ODataContext context, IEdmStructuredType structuredType) { OpenApiObject example = new OpenApiObject(); IEdmEntityType entityType = structuredType as IEdmEntityType; // properties foreach (var property in structuredType.Properties()) { // Remove properties of the same type as they are not supported by PowerApps if (property.Type.FullName() != structuredType.FullTypeName() && property.Type.FullName() != $"Collection({structuredType.FullTypeName()})") { // IOpenApiAny item; IEdmTypeReference propertyType = property.Type; IOpenApiAny item = GetTypeNameForExample(context, propertyType); EdmTypeKind typeKind = propertyType.TypeKind(); if (typeKind == EdmTypeKind.Primitive && item is OpenApiString) { OpenApiString stringAny = item as OpenApiString; string value = stringAny.Value; if (entityType != null && entityType.Key().Any(k => k.Name == property.Name)) { value += " (identifier)"; } if (propertyType.IsDateTimeOffset() || propertyType.IsDate() || propertyType.IsTimeOfDay()) { value += " (timestamp)"; } item = new OpenApiString(value); } example.Add(property.Name, item); } } return(example); }
/// <summary> /// Creates a new instance of the <see cref="EdmStructuralTypeInfo"/> class /// </summary> /// <param name="model">The Edm model.</param> /// <param name="structuredType">The Edm structured Type.</param> public EdmStructuralTypeInfo(IEdmModel model, IEdmStructuredType structuredType) { Contract.Assert(model != null); Contract.Assert(structuredType != null); foreach (var edmProperty in structuredType.Properties()) { switch (edmProperty.PropertyKind) { case EdmPropertyKind.Structural: if (AllStructuralProperties == null) { AllStructuralProperties = new HashSet <IEdmStructuralProperty>(); } AllStructuralProperties.Add((IEdmStructuralProperty)edmProperty); break; case EdmPropertyKind.Navigation: if (AllNavigationProperties == null) { AllNavigationProperties = new HashSet <IEdmNavigationProperty>(); } AllNavigationProperties.Add((IEdmNavigationProperty)edmProperty); break; } } IEdmEntityType entityType = structuredType as IEdmEntityType; if (entityType != null) { var actions = model.GetAvailableActions(entityType); AllActions = actions.Any() ? new HashSet <IEdmAction>(actions) : null; var functions = model.GetAvailableFunctions(entityType); AllFunctions = functions.Any() ? new HashSet <IEdmFunction>(functions) : null; } }
/// <summary> /// Resolve the <see cref="IEdmProperty"/> using the property name. This method supports the property name case insensitive. /// However, ODL only support case-sensitive. /// </summary> /// <param name="structuredType">The given structural type </param> /// <param name="propertyName">The given property name.</param> /// <returns>The resolved <see cref="IEdmProperty"/>.</returns> public static IEdmProperty ResolveProperty(this IEdmStructuredType structuredType, string propertyName) { if (structuredType == null) { throw Error.ArgumentNull(nameof(structuredType)); } bool ambiguous = false; IEdmProperty edmProperty = null; foreach (var property in structuredType.Properties()) { string name = property.Name; if (name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)) { if (name.Equals(propertyName, StringComparison.Ordinal)) { return(property); } else if (edmProperty != null) { ambiguous = true; } else { edmProperty = property; } } } if (ambiguous) { throw new ODataException(Error.Format(SRResources.AmbiguousPropertyNameFound, propertyName)); } return(edmProperty); }
void VisitModel(IEdmStructuredType modelType) { var querySettings = model.GetAnnotationValue <ModelBoundQuerySettings>(modelType); if (querySettings == null) { return; } var properties = new HashSet <string>(modelType.Properties().Select(p => p.Name), StringComparer.OrdinalIgnoreCase); VisitSelect(querySettings, properties); VisitExpand(querySettings, properties); if (IsSingleResult) { return; } VisitCount(querySettings); VisitFilter(querySettings, properties); VisitOrderBy(querySettings, properties); VisitMaxTop(querySettings); }
private static string GetEdmPropertyName(MemberInfo currentProperty, IEdmStructuredType edmType) { Contract.Requires(currentProperty != null); Contract.Requires(edmType != null); var edmProperty = edmType.Properties().SingleOrDefault(property => property.Name.Equals(currentProperty.Name, StringComparison.CurrentCultureIgnoreCase)); return edmProperty != null ? GetPropertyNameForEdmModel(currentProperty, edmProperty) : null; }
private static RecordSchema GetSchemaFromModel(IEdmStructuredType type) { if (type.IsOpen) { throw new ApplicationException("not supported."); } RecordSchema rs = Schema.CreateRecord(type.FullTypeName(), null); Schema.SetFields(rs, type.Properties().Select(property => Schema.CreateField(property.Name, GetSchemaFromModel(property.Type)))); return rs; }
/// <summary> /// Resolve property from property name /// </summary> /// <param name="type">The declaring type.</param> /// <param name="propertyName">The property name.</param> /// <returns>The resolved <see cref="IEdmProperty"/></returns> public virtual IEdmProperty ResolveProperty(IEdmStructuredType type, string propertyName) { if (EnableCaseInsensitive) { var result = type.Properties() .Where(_ => string.Equals(propertyName, _.Name, StringComparison.OrdinalIgnoreCase)) .ToList(); if (result.Count == 1) { return result.Single(); } else if (result.Count > 1) { throw new ODataException(Strings.UriParserMetadata_MultipleMatchingPropertiesFound(propertyName, type.FullTypeName())); } } return type.FindProperty(propertyName); }
/// <summary> /// Compares two sets of navigation properties (expected value in CSDL, actual as IEdmStructuredType). /// </summary> /// <param name="navigationPropertyElements">The CSDL element representing the properties.</param> /// <param name="structuredType">The EDM model type to compare against.</param> private static void CompareNavigationProperties(IEnumerable <XElement> navigationPropertyElements, IEdmStructuredType structuredType) { string structuredTypeName = structuredType.TestFullName(); var navigationProperties = structuredType.Properties().OfType <IEdmNavigationProperty>().ToArray(); ExceptionUtilities.Assert(navigationPropertyElements.Count() == navigationProperties.Count(), "Unexpected number of navigation properties on type " + structuredTypeName); foreach (var navigationPropertyElement in navigationPropertyElements) { var propertyName = navigationPropertyElement.GetAttributeValue("Name"); var navigationProperty = navigationProperties.SingleOrDefault(np => np.Name == propertyName); ExceptionUtilities.Assert(navigationProperty != null, "Failed to find navigation property " + propertyName + " on type " + structuredTypeName); CompareType(navigationPropertyElement, navigationProperty.Type); // Compare NavigationProperty Partner, if present var partner = navigationPropertyElement.Attribute("Partner"); if (partner == null) { ExceptionUtilities.Assert(navigationProperty.Partner == null, "Did not expect a Partner value for navigation property " + propertyName + " on type " + structuredTypeName); } else { ExceptionUtilities.Assert(navigationProperty.Partner != null, "Expected a Partner value for navigation property " + propertyName + " on type " + structuredTypeName); ExceptionUtilities.Assert(partner.Value == navigationProperty.Partner.Name, "Unexpected value for navigation property partner"); } // Compare any referential constraints var referentialConstraintElements = navigationPropertyElement.EdmElements("ReferentialConstraint").ToArray(); if (referentialConstraintElements.Any()) { ExceptionUtilities.Assert(navigationProperty.ReferentialConstraint != null, "Expected a referential constraint to be present"); ExceptionUtilities.Assert(referentialConstraintElements.Count() == navigationProperty.ReferentialConstraint.PropertyPairs.Count(), "Unexpected number of referential constraint pairs"); foreach (var referentialConstraintElement in referentialConstraintElements) { var principalProperty = referentialConstraintElement.GetAttributeValue("ReferencedProperty"); var referencedProperty = referentialConstraintElement.GetAttributeValue("Property"); var constraintPair = navigationProperty.ReferentialConstraint.PropertyPairs .SingleOrDefault(p => p.PrincipalProperty.Name == principalProperty && p.DependentProperty.Name == referencedProperty); ExceptionUtilities.Assert(constraintPair != null, "Failed to find constraint pair (" + principalProperty + ", " + referencedProperty + ")"); } } else { ExceptionUtilities.Assert(navigationProperty.ReferentialConstraint == null, "Did not expect any referential constraints"); } // Compare OnDelete, if present var onDeleteElement = navigationPropertyElement.EdmElements("OnDelete").SingleOrDefault(); if (onDeleteElement != null) { EdmOnDeleteAction expectedAction; EdmOnDeleteAction.TryParse(onDeleteElement.GetAttributeValue("Action"), out expectedAction); ExceptionUtilities.Assert(expectedAction == navigationProperty.OnDelete, "Unexpected value for OnDelete"); } else { ExceptionUtilities.Assert(EdmOnDeleteAction.None == navigationProperty.OnDelete, "Unexpected value for OnDelete"); } } }
private static ISet <IEdmStructuralProperty> GetPropertiesToIncludeInQuery( SelectExpandClause selectExpandClause, IEdmStructuredType structuredType, IEdmNavigationSource navigationSource, IEdmModel model, out ISet <IEdmStructuralProperty> autoSelectedProperties) { IEdmEntityType entityType = structuredType as IEdmEntityType; autoSelectedProperties = new HashSet <IEdmStructuralProperty>(); HashSet <IEdmStructuralProperty> propertiesToInclude = new HashSet <IEdmStructuralProperty>(); IEnumerable <SelectItem> selectedItems = selectExpandClause.SelectedItems; if (!IsSelectAll(selectExpandClause)) { // only select requested properties and keys. foreach (PathSelectItem pathSelectItem in selectedItems.OfType <PathSelectItem>()) { SelectExpandNode.ValidatePathIsSupportedForSelect(pathSelectItem.SelectedPath); PropertySegment structuralPropertySegment = pathSelectItem.SelectedPath.LastSegment as PropertySegment; if (structuralPropertySegment != null) { propertiesToInclude.Add(structuralPropertySegment.Property); } } foreach (ExpandedNavigationSelectItem expandedNavigationSelectItem in selectedItems.OfType <ExpandedNavigationSelectItem>()) { foreach (var segment in expandedNavigationSelectItem.PathToNavigationProperty) { PropertySegment propertySegment = segment as PropertySegment; if (propertySegment != null && structuredType.Properties().Contains(propertySegment.Property)) { propertiesToInclude.Add(propertySegment.Property); break; } } } if (entityType != null) { // add keys foreach (IEdmStructuralProperty keyProperty in entityType.Key()) { if (!propertiesToInclude.Contains(keyProperty)) { autoSelectedProperties.Add(keyProperty); } } } // add concurrency properties, if not added if (navigationSource != null && model != null) { IEnumerable <IEdmStructuralProperty> concurrencyProperties = model.GetConcurrencyProperties(navigationSource); foreach (IEdmStructuralProperty concurrencyProperty in concurrencyProperties) { if (!propertiesToInclude.Contains(concurrencyProperty)) { autoSelectedProperties.Add(concurrencyProperty); } } } } return(propertiesToInclude); }
private void ValidateAnnotationWithMorePropertyThanType(IEdmModel model, IEdmStructuredType actualType, IEnumerable<IEdmPropertyConstructor> annotationProperties) { var actualProperties = actualType.Properties(); foreach (var actualProperty in actualProperties) { var annotationProperty = annotationProperties.Where(n => n.Name.Equals(actualProperty.Name)).FirstOrDefault(); Assert.IsNotNull(annotationProperty, "Invalid property name."); Action<IEdmModel, IEdmStructuredType, IEnumerable<IEdmPropertyConstructor>> validateAnnotation = (m, t, l) => this.ValidateAnnotationWithMorePropertyThanType(m, t, l); ValidateAnnotationProperty(model, actualProperty, annotationProperty, validateAnnotation); } }
private void ValidateAnnotationWithExactPropertyAsType(IEdmModel model, IEdmStructuredType actualType, IEnumerable<IEdmPropertyConstructor> annotationProperties) { Assert.AreEqual(actualType.Properties().Count(), annotationProperties.Count(), "Annotation does not have the same count of properties as it's declared type."); foreach (var annotationProperty in annotationProperties) { var annotationName = annotationProperty.Name; var actualProperty = actualType.FindProperty(annotationName); Assert.IsNotNull(actualProperty, "Invalid property name."); Action<IEdmModel, IEdmStructuredType, IEnumerable<IEdmPropertyConstructor>> validateAnnotation = (m, t, l) => this.ValidateAnnotationWithExactPropertyAsType(m, t, l); ValidateAnnotationProperty(model, actualProperty, annotationProperty, validateAnnotation); } }
private void SetMimeTypeForProperties(IEdmStructuredType edmStructuredType) { Func<IEdmProperty, bool> predicate = null; Func<IEdmProperty, bool> func2 = null; MimeTypePropertyAttribute attribute = (MimeTypePropertyAttribute) this.GetClientTypeAnnotation(edmStructuredType).ElementType.GetCustomAttributes(typeof(MimeTypePropertyAttribute), true).SingleOrDefault<object>(); if (attribute != null) { if (predicate == null) { predicate = p => p.Name == attribute.DataPropertyName; } IEdmProperty edmProperty = edmStructuredType.Properties().SingleOrDefault<IEdmProperty>(predicate); if (edmProperty == null) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.ClientType_MissingMimeTypeDataProperty(this.GetClientTypeAnnotation(edmStructuredType).ElementTypeName, attribute.DataPropertyName)); } if (func2 == null) { func2 = p => p.Name == attribute.MimeTypePropertyName; } IEdmProperty property2 = edmStructuredType.Properties().SingleOrDefault<IEdmProperty>(func2); if (property2 == null) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.ClientType_MissingMimeTypeProperty(this.GetClientTypeAnnotation(edmStructuredType).ElementTypeName, attribute.MimeTypePropertyName)); } this.GetClientPropertyAnnotation(edmProperty).MimeTypeProperty = this.GetClientPropertyAnnotation(property2); } }
internal void WriteTypeStaticCreateMethod(string typeName, IEdmStructuredType structuredType) { Debug.Assert(structuredType != null, "structuredType != null"); if (structuredType.IsAbstract) { return; } Func<IEdmProperty, bool> hasDefault = p => p.PropertyKind == EdmPropertyKind.Structural && ((IEdmStructuralProperty)p).DefaultValueString != null; if (Context.EnableNamingAlias) { typeName = Customization.CustomizeNaming(typeName); } var parameters = structuredType.Properties() .Where(p => !p.Type.IsNullable && !p.Type.IsCollection() && !hasDefault(p)); if (!parameters.Any()) { return; } WriteSummaryCommentForStaticCreateMethod(typeName); var uniqueIdentifierService = new UniqueIdentifierService( /*IsLanguageCaseSensitive*/true); var instanceName = GetFixedName(uniqueIdentifierService.GetUniqueParameterName(typeName)); var propertyToParameterNamePairs = parameters .Select(p => new KeyValuePair<IEdmProperty, string>(p, uniqueIdentifierService.GetUniqueParameterName( IdentifierMappings.ContainsKey(p.Name) ? IdentifierMappings[p.Name] : p.Name))) .ToArray(); foreach (var propertyToParameterNamePair in propertyToParameterNamePairs) { var propertyName = propertyToParameterNamePair.Key.Name; propertyName = IdentifierMappings.ContainsKey(propertyName) ? IdentifierMappings[propertyName] : (Context.EnableNamingAlias ? Customization.CustomizeNaming(propertyName) : propertyName); WriteParameterCommentForStaticCreateMethod(propertyToParameterNamePair.Value, propertyName); } propertyToParameterNamePairs = propertyToParameterNamePairs .Select(p => p = new KeyValuePair<IEdmProperty, string>(p.Key, GetFixedName(p.Value))) .ToArray(); WriteDeclarationStartForStaticCreateMethod(typeName, GetFixedName(typeName)); WriteStaticCreateMethodParameters(propertyToParameterNamePairs); WriteDeclarationEndForStaticCreateMethod(GetFixedName(typeName), instanceName); foreach (var propertyToParameterNamePair in propertyToParameterNamePairs) { var property = propertyToParameterNamePair.Key; var parameterName = propertyToParameterNamePair.Value; Debug.Assert(!property.Type.IsCollection(), "!property.Type.IsCollection()"); Debug.Assert(!property.Type.IsNullable, "!property.Type.IsNullable"); // The static create method only sets non-nullable properties. We should add the null check if the type of the property is not a clr ValueType. // For now we add the null check if the property type is non-primitive. We should add the null check for non-ValueType primitives in the future. if (!property.Type.IsPrimitive() && !property.Type.IsEnum()) { WriteParameterNullCheckForStaticCreateMethod(parameterName); } var uniqIdentifier = IdentifierMappings.ContainsKey(property.Name) ? IdentifierMappings[property.Name] : (Context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name); WritePropertyValueAssignmentForStaticCreateMethod(instanceName, GetFixedName(uniqIdentifier), parameterName); } WriteMethodEndForStaticCreateMethod(instanceName); }
// This is to solve duplicate names between property and type internal void SetPropertyIdentifierMappingsIfNameConflicts(string typeName, IEdmStructuredType structuredType) { if (Context.EnableNamingAlias) { typeName = Customization.CustomizeNaming(typeName); } // PropertyName in VB is case-insensitive. var isLanguageCaseSensitive = true; // In VB, it is allowed that a type has a property whose name is same with the type's name var allowPropertyNameSameWithTypeName = false; Func<string, string> customizePropertyName = name => { return Context.EnableNamingAlias ? Customization.CustomizeNaming(name) : name; }; var propertyGroups = structuredType.Properties() .GroupBy(p => isLanguageCaseSensitive ? customizePropertyName(p.Name) : customizePropertyName(p.Name).ToUpperInvariant()); // If the group contains more than one property, or the property in the group has the same name with the type (only for C#), we need to rename the property var propertyToBeRenamedGroups = propertyGroups.Where(g => g.Count() > 1 || !allowPropertyNameSameWithTypeName && g.Key == typeName); var knownIdentifiers = propertyGroups.Select(g => customizePropertyName(g.First().Name)).ToList(); if (!allowPropertyNameSameWithTypeName && !knownIdentifiers.Contains(typeName)) { knownIdentifiers.Add(typeName); } var uniqueIdentifierService = new UniqueIdentifierService(knownIdentifiers, isLanguageCaseSensitive); IdentifierMappings.Clear(); foreach (var g in propertyToBeRenamedGroups) { var hasPropertyNameSameWithCustomizedPropertyName = false; var itemCount = g.Count(); for (var i = 0; i < itemCount; i++) { var property = g.ElementAt(i); var customizedPropertyName = customizePropertyName(property.Name); if (Context.EnableNamingAlias && customizedPropertyName == property.Name) { hasPropertyNameSameWithCustomizedPropertyName = true; } if (isLanguageCaseSensitive) { // If a property name is same as its customized property name, then we don't rename it. // Or we don't rename the last property in the group if (customizedPropertyName != typeName && (customizedPropertyName == property.Name || (!hasPropertyNameSameWithCustomizedPropertyName && i == itemCount - 1))) { continue; } } else { // When EnableNamingAlias = true, If a property name is same as its customized property name, then we don't rename it. // Or we don't rename the last property in the group. if ((Context.EnableNamingAlias && customizedPropertyName == property.Name) || (!hasPropertyNameSameWithCustomizedPropertyName && i == itemCount - 1)) { continue; } } var renamedPropertyName = uniqueIdentifierService.GetUniqueIdentifier(customizedPropertyName); IdentifierMappings.Add(property.Name, renamedPropertyName); } } }
/// <summary> /// Find properties with dynamic MIME type related properties and /// set the references from each ClientProperty to its related MIME type property /// </summary> /// <param name="edmStructuredType">Client edm type instance to wire up the mime type properties.</param> private void SetMimeTypeForProperties(IEdmStructuredType edmStructuredType) { MimeTypePropertyAttribute attribute = (MimeTypePropertyAttribute)this.GetClientTypeAnnotation(edmStructuredType).ElementType.GetCustomAttributes(typeof(MimeTypePropertyAttribute), true).SingleOrDefault(); if (null != attribute) { IEdmProperty dataProperty = edmStructuredType.Properties().SingleOrDefault(p => p.Name == attribute.DataPropertyName); if (dataProperty == null) { throw c.Error.InvalidOperation(c.Strings.ClientType_MissingMimeTypeDataProperty(this.GetClientTypeAnnotation(edmStructuredType).ElementTypeName, attribute.DataPropertyName)); } IEdmProperty mimeTypeProperty = edmStructuredType.Properties().SingleOrDefault(p => p.Name == attribute.MimeTypePropertyName); if (mimeTypeProperty == null) { throw c.Error.InvalidOperation(c.Strings.ClientType_MissingMimeTypeProperty(this.GetClientTypeAnnotation(edmStructuredType).ElementTypeName, attribute.MimeTypePropertyName)); } this.GetClientPropertyAnnotation(dataProperty).MimeTypeProperty = this.GetClientPropertyAnnotation(mimeTypeProperty); } }
/// <inheritdoc /> public Type NewStructuredType(IEdmStructuredType structuredType, Type clrType, ApiVersion apiVersion, IEdmModel edmModel) { Arg.NotNull(structuredType, nameof(structuredType)); Arg.NotNull(clrType, nameof(clrType)); Arg.NotNull(apiVersion, nameof(apiVersion)); Arg.NotNull(edmModel, nameof(edmModel)); Contract.Ensures(Contract.Result <Type>() != null); var typeKey = new EdmTypeKey(structuredType, apiVersion); if (generatedEdmTypes.TryGetValue(typeKey, out var generatedType)) { return(generatedType); } visitedEdmTypes.Add(typeKey); const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; var properties = new List <ClassProperty>(); var structuralProperties = structuredType.Properties().ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase); var clrTypeMatchesEdmType = true; var hasUnfinishedTypes = false; var dependentProperties = new List <PropertyDependency>(); foreach (var property in clrType.GetProperties(bindingFlags)) { if (!structuralProperties.TryGetValue(property.Name, out var structuralProperty)) { clrTypeMatchesEdmType = false; continue; } var structuredTypeRef = structuralProperty.Type; var propertyType = property.PropertyType; var propertyTypeKey = new EdmTypeKey(structuredTypeRef, apiVersion); if (structuredTypeRef.IsCollection()) { var collectionType = structuredTypeRef.AsCollection(); var elementType = collectionType.ElementType(); if (elementType.IsStructured()) { visitedEdmTypes.Add(propertyTypeKey); var itemType = elementType.Definition.GetClrType(edmModel); var elementKey = new EdmTypeKey(elementType, apiVersion); if (visitedEdmTypes.Contains(elementKey)) { clrTypeMatchesEdmType = false; hasUnfinishedTypes = true; var dependency = new PropertyDependency(elementKey, true, property.Name); dependentProperties.Add(dependency); continue; } var newItemType = NewStructuredType(elementType.ToStructuredType(), itemType, apiVersion, edmModel); if (newItemType is TypeBuilder) { hasUnfinishedTypes = true; } if (!itemType.Equals(newItemType)) { propertyType = IEnumerableOfT.MakeGenericType(newItemType); clrTypeMatchesEdmType = false; } } } else if (structuredTypeRef.IsStructured()) { if (!visitedEdmTypes.Contains(propertyTypeKey)) { propertyType = NewStructuredType(structuredTypeRef.ToStructuredType(), propertyType, apiVersion, edmModel); if (propertyType is TypeBuilder) { hasUnfinishedTypes = true; } } else { clrTypeMatchesEdmType = false; hasUnfinishedTypes = true; var dependency = new PropertyDependency(propertyTypeKey, false, property.Name); dependentProperties.Add(dependency); continue; } } clrTypeMatchesEdmType &= property.PropertyType.Equals(propertyType); properties.Add(new ClassProperty(property, propertyType)); } if (clrTypeMatchesEdmType) { return(generatedEdmTypes.GetOrAdd(typeKey, clrType.GetTypeInfo())); } var signature = new ClassSignature(clrType, properties, apiVersion); if (hasUnfinishedTypes) { if (!unfinishedTypes.TryGetValue(typeKey, out var typeBuilder)) { typeBuilder = CreateTypeBuilderFromSignature(signature); foreach (var propertyDependency in dependentProperties) { propertyDependency.DependentType = typeBuilder; } dependencies.Add(typeKey, dependentProperties); ResolveForUnfinishedTypes(); return(ResolveDependencies(typeBuilder, typeKey)); } return(typeBuilder); } return(generatedEdmTypes.GetOrAdd(typeKey, CreateTypeInfoFromSignature(signature))); }
private static IEdmProperty FindEdmProperty(IEdmStructuredType edmType, String name) { return(edmType.Properties().Single(p => String.Compare(p.Name, name, StringComparison.OrdinalIgnoreCase) == 0)); }
/// <inheritdoc/> public override IEnumerable <string> GetUnchangedPropertyNames() { return(_actualEdmType.Properties().Select(p => p.Name).Except(GetChangedPropertyNames())); }
static Type GenerateTypeIfNeeded(IEdmStructuredType structuredType, BuilderContext context) { var apiVersion = context.ApiVersion; var edmTypes = context.EdmTypes; var typeKey = new EdmTypeKey(structuredType, apiVersion); if (edmTypes.TryGetValue(typeKey, out var generatedType)) { return(generatedType); } var edmModel = context.EdmModel; var clrType = structuredType.GetClrType(edmModel); var visitedEdmTypes = context.VisitedEdmTypes; visitedEdmTypes.Add(typeKey); const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; var properties = new List <ClassProperty>(); var structuralProperties = structuredType.Properties().ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase); var clrTypeMatchesEdmType = true; var hasUnfinishedTypes = false; var dependentProperties = new List <PropertyDependency>(); foreach (var property in clrType.GetProperties(bindingFlags)) { if (!structuralProperties.TryGetValue(property.Name, out var structuralProperty)) { clrTypeMatchesEdmType = false; continue; } var structuredTypeRef = structuralProperty.Type; var propertyType = property.PropertyType; var propertyTypeKey = new EdmTypeKey(structuredTypeRef, apiVersion); if (structuredTypeRef.IsCollection()) { var collectionType = structuredTypeRef.AsCollection(); var elementType = collectionType.ElementType(); if (elementType.IsStructured()) { visitedEdmTypes.Add(propertyTypeKey); var itemType = elementType.Definition.GetClrType(edmModel); var elementKey = new EdmTypeKey(elementType, apiVersion); if (visitedEdmTypes.Contains(elementKey)) { clrTypeMatchesEdmType = false; hasUnfinishedTypes = true; dependentProperties.Add(new PropertyDependency(elementKey, true, property.Name)); continue; } var newItemType = GenerateTypeIfNeeded(elementType.ToStructuredType(), context); if (newItemType is TypeBuilder) { hasUnfinishedTypes = true; } if (!itemType.Equals(newItemType)) { propertyType = IEnumerableOfT.MakeGenericType(newItemType); clrTypeMatchesEdmType = false; } } } else if (structuredTypeRef.IsStructured()) { if (!visitedEdmTypes.Contains(propertyTypeKey)) { propertyType = GenerateTypeIfNeeded(structuredTypeRef.ToStructuredType(), context); if (propertyType is TypeBuilder) { hasUnfinishedTypes = true; } } else { clrTypeMatchesEdmType = false; hasUnfinishedTypes = true; dependentProperties.Add(new PropertyDependency(propertyTypeKey, false, property.Name)); continue; } } clrTypeMatchesEdmType &= property.PropertyType.Equals(propertyType); properties.Add(new ClassProperty(property, propertyType)); } var type = default(TypeInfo); if (clrTypeMatchesEdmType) { if (!edmTypes.TryGetValue(typeKey, out type)) { edmTypes.Add(typeKey, type = clrType.GetTypeInfo()); } return(type); } var signature = new ClassSignature(clrType, properties, apiVersion); if (hasUnfinishedTypes) { if (edmTypes.TryGetValue(typeKey, out type)) { return(type); } var typeBuilder = CreateTypeBuilderFromSignature(context.ModuleBuilder, signature); var dependencies = context.Dependencies; foreach (var propertyDependency in dependentProperties) { propertyDependency.DependentType = typeBuilder; dependencies.Add(propertyDependency); } edmTypes.Add(typeKey, typeBuilder); return(typeBuilder); } if (!edmTypes.TryGetValue(typeKey, out type)) { edmTypes.Add(typeKey, type = CreateTypeInfoFromSignature(context.ModuleBuilder, signature)); } return(type); }