Beispiel #1
0
        /// <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);
            }
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #5
0
            /// <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;
                }
            }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        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;
        }
Beispiel #10
0
        /// <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");
                }
            }
        }
Beispiel #12
0
        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);
            }
        }
Beispiel #15
0
 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);
                }
            }
        }
Beispiel #18
0
        /// <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)));
        }
Beispiel #20
0
 private static IEdmProperty FindEdmProperty(IEdmStructuredType edmType, String name)
 {
     return(edmType.Properties().Single(p => String.Compare(p.Name, name, StringComparison.OrdinalIgnoreCase) == 0));
 }
Beispiel #21
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);
        }