Esempio n. 1
0
        private bool TryProcessDeltaNestedResource(IEdmProperty nestedProperty, object resource, ODataResourceWrapper resourceWrapper, ODataDeserializerContext readContext)
        {
            string nestedPropertyName = EdmLibHelpers.GetClrPropertyName(nestedProperty, readContext.Model);
            IDelta resourceDelta      = resource as IDelta;

            if (resourceDelta == null)
            {
                return(false);
            }

            if (resourceWrapper == null)
            {
                return(resourceDelta.TrySetPropertyReferencedValue(nestedPropertyName, null));
            }

            if (resourceWrapper.Resource.Properties == null)
            {
                return(false);
            }

            IEdmStructuredTypeReference structuredType = nestedProperty.Type.AsStructured();
            Delta propertyValueDelta = CreateDeltaInstance(readContext, resourceWrapper, structuredType);

            ApplyResourceProperties(propertyValueDelta, resourceWrapper, structuredType, readContext);

            return(resourceDelta.TrySetPropertyReferencedValue(nestedPropertyName, propertyValueDelta));
        }
Esempio n. 2
0
        private Expression CreatePropertyAccessExpression(Expression source, IEdmProperty property, string propertyPath = null)
        {
            string propertyName = EdmLibHelpers.GetClrPropertyName(property, this.Model);

            propertyPath = propertyPath ?? propertyName;
            if (this.QuerySettings.HandleNullPropagation == HandleNullPropagationOption.True && IsNullable(source.Type) &&
                source != this._lambdaParameter)
            {
                Expression cleanSource = this.RemoveInnerNullPropagation(source);
                Expression propertyAccessExpression = null;
                propertyAccessExpression = this.GetFlattenedPropertyExpression(propertyPath) ?? Expression.Property(cleanSource, propertyName);

                // source.property => source == null ? null : [CastToNullable]RemoveInnerNullPropagation(source).property
                // Notice that we are checking if source is null already. so we can safely remove any null checks when doing source.Property

                Expression ifFalse = ToNullable(this.ConvertNonStandardPrimitives(propertyAccessExpression));
                return
                    (Expression.Condition(
                         test: Expression.Equal(source, NullConstant),
                         ifTrue: Expression.Constant(null, ifFalse.Type),
                         ifFalse: ifFalse));
            }
            else
            {
                return(this.GetFlattenedPropertyExpression(propertyPath) ?? this.ConvertNonStandardPrimitives(Expression.Property(source, propertyName)));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Generates a string to be used as the skip token value within the next link.
        /// </summary>
        /// <param name="lastMember"> Object based on which SkipToken value will be generated.</param>
        /// <param name="model">The edm model.</param>
        /// <param name="orderByNodes">List of orderByNodes used to generate the skiptoken value.</param>
        /// <returns>Value for the skiptoken to be used in the next link.</returns>
        private static string GenerateSkipTokenValue(Object lastMember, IEdmModel model, IList <OrderByNode> orderByNodes)
        {
            if (lastMember == null)
            {
                return(String.Empty);
            }

            IEnumerable <IEdmProperty> propertiesForSkipToken = GetPropertiesForSkipToken(lastMember, model, orderByNodes);
            StringBuilder skipTokenBuilder = new StringBuilder(String.Empty);

            if (propertiesForSkipToken == null)
            {
                return(skipTokenBuilder.ToString());
            }

            int    count = 0;
            string uriLiteral;
            object value;
            int    lastIndex         = propertiesForSkipToken.Count() - 1;
            IEdmStructuredObject obj = lastMember as IEdmStructuredObject;

            foreach (IEdmProperty edmProperty in propertiesForSkipToken)
            {
                bool   islast          = count == lastIndex;
                string clrPropertyName = EdmLibHelpers.GetClrPropertyName(edmProperty, model);
                if (obj != null)
                {
                    obj.TryGetPropertyValue(clrPropertyName, out value);
                }
                else
                {
                    value = lastMember.GetType().GetProperty(clrPropertyName).GetValue(lastMember);
                }

                if (value == null)
                {
                    uriLiteral = ODataUriUtils.ConvertToUriLiteral(value, ODataVersion.V401);
                }
                else if (edmProperty.Type.IsEnum())
                {
                    ODataEnumValue enumValue = new ODataEnumValue(value.ToString(), value.GetType().FullName);
                    uriLiteral = ODataUriUtils.ConvertToUriLiteral(enumValue, ODataVersion.V401, model);
                }
                else if (edmProperty.Type.IsDateTimeOffset() && value is DateTime)
                {
                    var dateTime            = (DateTime)value;
                    var dateTimeOffsetValue = TimeZoneInfoHelper.ConvertToDateTimeOffset(dateTime);
                    uriLiteral = ODataUriUtils.ConvertToUriLiteral(dateTimeOffsetValue, ODataVersion.V401, model);
                }
                else
                {
                    uriLiteral = ODataUriUtils.ConvertToUriLiteral(value, ODataVersion.V401, model);
                }

                skipTokenBuilder.Append(edmProperty.Name).Append(propertyDelimiter).Append(uriLiteral).Append(islast ? String.Empty : CommaDelimiter.ToString());
                count++;
            }

            return(skipTokenBuilder.ToString());
        }
Esempio n. 4
0
        internal static void ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, object resource,
                                           ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)
        {
            IEdmProperty edmProperty = resourceType.FindProperty(property.Name);

            bool   isDynamicProperty = false;
            string propertyName      = property.Name;

            if (edmProperty != null)
            {
                propertyName = EdmLibHelpers.GetClrPropertyName(edmProperty, readContext.Model);
            }
            else
            {
                IEdmStructuredType structuredType = resourceType.StructuredDefinition();
                isDynamicProperty = structuredType != null && structuredType.IsOpen;
            }

            // dynamic properties have null values
            IEdmTypeReference propertyType = edmProperty != null ? edmProperty.Type : null;

            EdmTypeKind propertyKind;
            object      value = ConvertValue(property.Value, ref propertyType, deserializerProvider, readContext,
                                             out propertyKind);

            if (isDynamicProperty)
            {
                SetDynamicProperty(resource, resourceType, propertyKind, propertyName, value, propertyType,
                                   readContext);
            }
            else
            {
                SetDeclaredProperty(resource, propertyKind, propertyName, value, edmProperty, readContext);
            }
        }
Esempio n. 5
0
        private void ApplyResourceSetInNestedProperty(IEdmProperty nestedProperty, object resource,
                                                      ODataResourceSetWrapper resourceSetWrapper, ODataDeserializerContext readContext)
        {
            Contract.Assert(nestedProperty != null);
            Contract.Assert(resource != null);
            Contract.Assert(readContext != null);

            if (readContext.IsDeltaOfT)
            {
                IEdmNavigationProperty navigationProperty = nestedProperty as IEdmNavigationProperty;
                if (navigationProperty != null)
                {
                    if (TryProcessDeltaNestedResourceSet(nestedProperty, resource, resourceSetWrapper, readContext))
                    {
                        return;
                    }

                    string message = Error.Format(SRResources.CannotPatchNavigationProperties, navigationProperty.Name,
                                                  navigationProperty.DeclaringEntityType().FullName());
                    throw new ODataException(message);
                }
            }

            object value = ReadNestedResourceSetInline(resourceSetWrapper, nestedProperty.Type, readContext);

            string propertyName = EdmLibHelpers.GetClrPropertyName(nestedProperty, readContext.Model);

            DeserializationHelpers.SetCollectionProperty(resource, nestedProperty, value, propertyName);
        }
        private void ApplyResourceInNestedProperty(IEdmProperty nestedProperty, object resource,
                                                   ODataResourceWrapper resourceWrapper, ODataDeserializerContext readContext)
        {
            Contract.Assert(nestedProperty != null);
            Contract.Assert(resource != null);
            Contract.Assert(readContext != null);

            if (readContext.IsDeltaOfT)
            {
                IEdmNavigationProperty navigationProperty = nestedProperty as IEdmNavigationProperty;
                if (navigationProperty != null)
                {
                    string message = Error.Format(SRResources.CannotPatchNavigationProperties, navigationProperty.Name,
                                                  navigationProperty.DeclaringEntityType().FullName());
                    throw new ODataException(message);
                }
            }

            object value = ReadNestedResourceInline(resourceWrapper, nestedProperty.Type, readContext);

            // First resolve Data member alias or annotation, then set the regular
            // or delta resource accordingly.
            string propertyName = EdmLibHelpers.GetClrPropertyName(nestedProperty, readContext.Model);

            DeserializationHelpers.SetProperty(resource, propertyName, value);
        }
Esempio n. 7
0
        public static IQueryable OrderByProperty(IQueryable query, IEdmModel model, IEdmProperty property, OrderByDirection direction, Type type, bool alreadyOrdered = false)
        {
            // property aliasing
            string           propertyName  = EdmLibHelpers.GetClrPropertyName(property, model);
            LambdaExpression orderByLambda = GetPropertyAccessLambda(type, propertyName);

            return(OrderBy(query, orderByLambda, direction, type, alreadyOrdered));
        }
Esempio n. 8
0
        /// <summary>
        /// Returns all updatable properties for given structured type.
        /// </summary>
        /// <param name="model">Edm model.</param>
        /// <param name="structuredType">The type of the resource.</param>
        /// <returns></returns>
        protected static IEnumerable <string> GetUpdatableProperties(IEdmModel model, IEdmStructuredTypeReference structuredType)
        {
            // we consider navigation properties to be editable so that @odata.id works for nested resources
            IEnumerable <string> updatableProperties = structuredType.StructuralProperties()
                                                       .Cast <IEdmProperty>()
                                                       .Union(structuredType.NavigationProperties())
                                                       .Select(edmProperty => EdmLibHelpers.GetClrPropertyName(edmProperty, model));

            return(updatableProperties);
        }
        internal static void ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, object resource,
                                           ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)
        {
            IEdmProperty edmProperty = resourceType.FindProperty(property.Name);

            // try to deserializer the dynamic properties for open type.
            if (edmProperty == null)
            {
                // the logic here works for open complex type and open entity type.
                IEdmStructuredType structuredType = resourceType.StructuredDefinition();
                if (structuredType != null && structuredType.IsOpen)
                {
                    if (ApplyDynamicProperty(property, structuredType, resource, deserializerProvider, readContext))
                    {
                        return;
                    }
                }
            }

            string propertyName = property.Name;

            if (edmProperty != null)
            {
                propertyName = EdmLibHelpers.GetClrPropertyName(edmProperty, readContext.Model);
            }
            IEdmTypeReference propertyType = edmProperty != null ? edmProperty.Type : null; // open properties have null values

            EdmTypeKind propertyKind;
            object      value = ConvertValue(property.Value, ref propertyType, deserializerProvider, readContext, out propertyKind);

            if (propertyKind == EdmTypeKind.Collection)
            {
                SetCollectionProperty(resource, edmProperty, value, propertyName);
            }
            else
            {
                if (!readContext.IsUntyped)
                {
                    if (propertyKind == EdmTypeKind.Primitive)
                    {
                        value = EdmPrimitiveHelpers.ConvertPrimitiveValue(value, GetPropertyType(resource, propertyName));
                    }
                    else if (propertyKind == EdmTypeKind.Enum)
                    {
                        value = EnumDeserializationHelpers.ConvertEnumValue(value, GetPropertyType(resource, propertyName));
                    }
                }

                SetProperty(resource, propertyName, value);
            }
        }
Esempio n. 10
0
        private object BuildResourceInstance()
        {
            if (EdmObject == null)
            {
                return(null);
            }

            TypedEdmStructuredObject edmStructruredObject = EdmObject as TypedEdmStructuredObject;

            if (edmStructruredObject != null)
            {
                return(edmStructruredObject.Instance);
            }

            SelectExpandWrapper selectExpandWrapper = EdmObject as SelectExpandWrapper;

            if (selectExpandWrapper != null && selectExpandWrapper.UntypedInstance != null)
            {
                return(selectExpandWrapper.UntypedInstance);
            }

            Type clrType = EdmLibHelpers.GetClrType(StructuredType, EdmModel);

            if (clrType == null)
            {
                throw new InvalidOperationException(Error.Format(SRResources.MappingDoesNotContainResourceType, StructuredType.FullTypeName()));
            }

            object resource = Activator.CreateInstance(clrType);

            foreach (IEdmStructuralProperty property in StructuredType.StructuralProperties())
            {
                object value;
                if (EdmObject.TryGetPropertyValue(property.Name, out value) && value != null)
                {
                    string propertyName = EdmLibHelpers.GetClrPropertyName(property, EdmModel);

                    if (value.GetType().IsCollection())
                    {
                        DeserializationHelpers.SetCollectionProperty(resource, property, value, propertyName);
                    }
                    else
                    {
                        DeserializationHelpers.SetProperty(resource, propertyName, value);
                    }
                }
            }

            return(resource);
        }
Esempio n. 11
0
        internal static Func <object, object> GetOrCreatePropertyGetter(
            Type type,
            string propertyName,
            IEdmStructuredTypeReference edmType,
            IEdmModel model,
            ref ConcurrentDictionary <string, Func <object, object> > propertyGetterCache)
        {
            EnsurePropertyGettingCachePopulated(type, edmType, model, ref propertyGetterCache);

            return(propertyGetterCache.GetOrAdd(propertyName, name =>
            {
                IEdmProperty property = edmType.FindProperty(name);
                if (property != null && model != null)
                {
                    name = EdmLibHelpers.GetClrPropertyName(property, model) ?? name;
                }

                return CreatePropertyGetter(type, name);
            }));
        }
        internal Expression CreatePropertyValueExpression(IEdmEntityType elementType, IEdmProperty property, Expression source)
        {
            Contract.Assert(elementType != null);
            Contract.Assert(property != null);
            Contract.Assert(source != null);

            IEdmEntityType declaringType = property.DeclaringType as IEdmEntityType;

            Contract.Assert(declaringType != null, "only entity types are projected.");

            // derived property using cast
            if (elementType != declaringType)
            {
                Type castType = EdmLibHelpers.GetClrType(declaringType, _model);
                if (castType == null)
                {
                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainEntityType, declaringType.FullName()));
                }

                source = Expression.TypeAs(source, castType);
            }

            string     propertyName  = EdmLibHelpers.GetClrPropertyName(property, _model);
            Expression propertyValue = Expression.Property(source, propertyName);

            if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
            {
                // source == null ? null : propertyValue
                propertyValue = Expression.Condition(
                    test: Expression.Equal(source, Expression.Constant(null)),
                    ifTrue: Expression.Constant(null, propertyValue.Type.ToNullable()),
                    ifFalse: ExpressionHelpers.ToNullable(propertyValue));
            }
            else
            {
                // need to cast this to nullable as EF would fail while materializing if the property is not nullable and source is null.
                propertyValue = ExpressionHelpers.ToNullable(propertyValue);
            }

            return(propertyValue);
        }
Esempio n. 13
0
        private bool TryProcessDeltaNestedResourceSet(IEdmProperty collectionProperty, object resource, ODataResourceSetWrapper resourceSetWrapper, ODataDeserializerContext readContext)
        {
            string collectionPropertyName = EdmLibHelpers.GetClrPropertyName(collectionProperty, readContext.Model);
            IDelta resourceDelta          = resource as IDelta;

            if (resourceDelta == null)
            {
                return(false);
            }

            if (resourceSetWrapper == null)
            {
                return(resourceDelta.TrySetPropertyReferencedValue(collectionPropertyName, null));
            }

            if (resourceSetWrapper.Resources == null)
            {
                return(false);
            }

            IEdmStructuredTypeReference structuredElementType = collectionProperty.Type.AsCollection().ElementType().AsStructured();

            Type clrElementType = EdmLibHelpers.GetClrType(structuredElementType, readContext.Model);
            Type deltaType      = typeof(Delta <>).MakeGenericType(clrElementType);

            IEnumerable <string> structuralProperties = GetUpdatableProperties(readContext.Model, structuredElementType);

            IList elementDeltas = new ArrayList();

            foreach (ODataResourceWrapper resourceWrapper in resourceSetWrapper.Resources)
            {
                Delta elementDelta = (Delta)Activator.CreateInstance(deltaType, clrElementType, structuralProperties);
                ApplyResourceProperties(elementDelta, resourceWrapper, structuredElementType, readContext);

                elementDeltas.Add(elementDelta);
            }

            return(resourceDelta.TrySetPropertyCollectionValue(collectionPropertyName, elementDeltas));
        }
Esempio n. 14
0
        private void ApplyFeedInNavigationProperty(IEdmNavigationProperty navigationProperty, object entityResource, ODataFeedWithEntries feed, ODataDeserializerContext readContext)
        {
            Contract.Assert(navigationProperty != null && navigationProperty.PropertyKind == EdmPropertyKind.Navigation, "navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType");
            Contract.Assert(entityResource != null, "entityResource != null");

            if (readContext.IsDeltaOfT)
            {
                string message = Error.Format(SRResources.CannotPatchNavigationProperties, navigationProperty.Name, navigationProperty.DeclaringEntityType().FullName());
                throw new ODataException(message);
            }

            ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(navigationProperty.Type);

            if (deserializer == null)
            {
                throw new SerializationException(Error.Format(SRResources.TypeCannotBeDeserialized, navigationProperty.Type.FullName(), typeof(ODataMediaTypeFormatter)));
            }
            object value = deserializer.ReadInline(feed, navigationProperty.Type, readContext);

            string propertyName = EdmLibHelpers.GetClrPropertyName(navigationProperty, readContext.Model);

            DeserializationHelpers.SetCollectionProperty(entityResource, navigationProperty, value, propertyName, readContext.TimeZoneInfo);
        }
        internal static Func <object, object> GetOrCreatePropertyGetter(
            Type type,
            string propertyName,
            IEdmStructuredTypeReference edmType,
            IEdmModel model)
        {
            Tuple <string, Type>  key = Tuple.Create(propertyName, type);
            Func <object, object> getter;

            if (!_propertyGetterCache.TryGetValue(key, out getter))
            {
                IEdmProperty property = edmType.FindProperty(propertyName);
                if (property != null && model != null)
                {
                    propertyName = EdmLibHelpers.GetClrPropertyName(property, model) ?? propertyName;
                }

                getter = CreatePropertyGetter(type, propertyName);
                _propertyGetterCache[key] = getter;
            }

            return(getter);
        }
Esempio n. 16
0
        internal static void ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, object resource,
                                           ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)
        {
            IEdmProperty edmProperty = resourceType.FindProperty(property.Name);

            string propertyName = property.Name;

            if (edmProperty != null)
            {
                propertyName = EdmLibHelpers.GetClrPropertyName(edmProperty, readContext.Model);
            }
            IEdmTypeReference propertyType = edmProperty != null ? edmProperty.Type : null; // open properties have null values

            EdmTypeKind propertyKind;
            object      value = ConvertValue(property.Value, ref propertyType, deserializerProvider, readContext, out propertyKind);

            if (propertyKind == EdmTypeKind.Collection)
            {
                SetCollectionProperty(resource, edmProperty, value, propertyName);
            }
            else
            {
                if (!readContext.IsUntyped)
                {
                    if (propertyKind == EdmTypeKind.Primitive)
                    {
                        value = EdmPrimitiveHelpers.ConvertPrimitiveValue(value, GetPropertyType(resource, propertyName));
                    }
                    else if (propertyKind == EdmTypeKind.Enum)
                    {
                        value = EnumDeserializationHelpers.ConvertEnumValue(value, GetPropertyType(resource, propertyName));
                    }
                }

                SetProperty(resource, propertyName, value);
            }
        }
Esempio n. 17
0
        private static void EnsurePropertyGettingCachePopulated(Type type, IEdmStructuredTypeReference edmType, IEdmModel model, ref ConcurrentDictionary <string, Func <object, object> > propertyGetterCache)
        {
            if (propertyGetterCache == null)
            {
                propertyGetterCache = _propertyGetterCache.GetOrAdd(type, t =>
                {
                    // Creating all property getters on first access to the type
                    // It will allows us to avoid growing dictionary from 0 to number of properties that means copy data over and over as soon as capacity reached

                    // First get all properties
                    var properties = edmType.StructuredDefinition().Properties().ToList();
                    // Create dictionary with right capacity
                    var result = new ConcurrentDictionary <string, Func <object, object> >(4 * Environment.ProcessorCount, properties.Count);

                    // Fill dictionary with getters for each property
                    foreach (IEdmProperty property in properties)
                    {
                        var name = EdmLibHelpers.GetClrPropertyName(property, model) ?? property.Name;
                        result.TryAdd(property.Name, CreatePropertyGetter(type, name));
                    }
                    return(result);
                });
            }
        }
Esempio n. 18
0
        private void ApplyDeltaResourceSetInNestedProperty(IEdmProperty nestedProperty, object resource,
                                                           ODataDeltaResourceSetWrapper resourceSetWrapper, ODataDeserializerContext readContext)
        {
            Contract.Assert(nestedProperty != null);
            Contract.Assert(resource != null);
            Contract.Assert(readContext != null);

            if (!readContext.IsDeltaOfT)
            {
                throw new ODataException("Read context of @odata.delta incorrect");
            }

            ICollection modifiedItems;
            ICollection deletedItems;

            ReadDeltaResourceSetInline(resourceSetWrapper, nestedProperty.Type, readContext, out modifiedItems, out deletedItems);

            IDelta resourceDelta = (IDelta)resource;

            string propertyName = EdmLibHelpers.GetClrPropertyName(nestedProperty, readContext.Model);

            resourceDelta.TrySetPropertyCollectionValue(propertyName, modifiedItems);
            resourceDelta.TrySetDeletedPropertyValue(propertyName, deletedItems);
        }
Esempio n. 19
0
        internal static object CreateResource(IEdmComplexTypeReference complexType, ODataDeserializerContext readContext)
        {
            if (complexType == null)
            {
                throw Error.ArgumentNull("complexType");
            }
            if (readContext == null)
            {
                throw Error.ArgumentNull("readContext");
            }

            IEdmModel model = readContext.Model;

            if (model == null)
            {
                throw Error.Argument("readContext", SRResources.ModelMissingFromReadContext);
            }

            if (readContext.IsUntyped)
            {
                return(new EdmComplexObject(complexType));
            }
            else
            {
                Type clrType = EdmLibHelpers.GetClrType(complexType, readContext.Model);
                if (clrType == null)
                {
                    throw Error.InvalidOperation(SRResources.MappingDoesNotContainEntityType, complexType.FullName());
                }

                if (readContext.IsDeltaOfT)
                {
                    Type elementType = readContext.ResourceType.GetGenericArguments()[0];
                    if (elementType != clrType)
                    {
                        // Just create the object for inline complex type
                        return(Activator.CreateInstance(clrType));
                    }

                    IEnumerable <string> structuralProperties = complexType.StructuralProperties()
                                                                .Select(edmProperty => EdmLibHelpers.GetClrPropertyName(edmProperty, model));

                    if (complexType.IsOpen())
                    {
                        PropertyInfo dynamicDictionaryPropertyInfo = EdmLibHelpers.GetDynamicPropertyDictionary(
                            complexType.StructuredDefinition(), model);

                        return(Activator.CreateInstance(readContext.ResourceType, clrType, structuralProperties,
                                                        dynamicDictionaryPropertyInfo));
                    }
                    else
                    {
                        return(Activator.CreateInstance(readContext.ResourceType, clrType, structuralProperties));
                    }
                }
                else
                {
                    return(Activator.CreateInstance(clrType));
                }
            }
        }
Esempio n. 20
0
        internal Expression CreatePropertyValueExpressionWithFilter(IEdmStructuredType elementType, IEdmProperty property,
                                                                    Expression source, ExpandedReferenceSelectItem expandItem)
        {
            Contract.Assert(elementType != null);
            Contract.Assert(property != null);
            Contract.Assert(source != null);

            FilterClause filterClause = expandItem != null ? expandItem.FilterOption : null;

            IEdmStructuredType declaringType;
            IEdmStructuredType currentType = elementType;

            if (expandItem != null)
            {
                foreach (ODataPathSegment segment in expandItem.PathToNavigationProperty)
                {
                    string          currentProperty           = String.Empty;
                    PropertySegment propertyAccessPathSegment =
                        segment as PropertySegment;
                    if (propertyAccessPathSegment != null)
                    {
                        IEdmProperty propertyInPath = propertyAccessPathSegment.Property;
                        currentProperty = EdmLibHelpers.GetClrPropertyName(propertyInPath, _model);
                        declaringType   = propertyInPath.DeclaringType;
                        Contract.Assert(!String.IsNullOrEmpty(currentProperty), "Property name could not be found on the model.");
                        if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
                        {
                            // create expression similar to: 'source == null ? null : propertyValue'
                            if (declaringType != currentType)
                            {
                                Type castType = EdmLibHelpers.GetClrType(property.DeclaringType, _model);
                                if (castType == null)
                                {
                                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainResourceType,
                                                                          property.DeclaringType.FullTypeName()));
                                }

                                source = Expression.TypeAs(source, castType);
                            }
                            Expression propertyExpression = Expression.Property(source, currentProperty);
                            Type       nullablePropType   = TypeHelper.ToNullable(propertyExpression.Type);

                            source = Expression.Condition(
                                test: Expression.Equal(propertyExpression, Expression.Constant(value: null)),
                                ifTrue: Expression.Constant(value: null, type: nullablePropType),
                                ifFalse: propertyExpression);
                        }
                        else
                        {
                            source = Expression.Property(source, currentProperty);
                        }

                        currentType = propertyInPath.Type.ToStructuredType();
                    }
                    else
                    {
                        TypeSegment typeSegment = segment as TypeSegment;
                        if (typeSegment != null)
                        {
                            Type castType = EdmLibHelpers.GetClrType(typeSegment.EdmType, _model);
                            source      = Expression.TypeAs(source, castType);
                            currentType = typeSegment.EdmType as IEdmStructuredType;
                        }
                    }
                }
            }

            // derived property using cast
            if (currentType != property.DeclaringType)
            {
                Type castType = EdmLibHelpers.GetClrType(property.DeclaringType, _model);
                if (castType == null)
                {
                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainResourceType,
                                                          property.DeclaringType.FullTypeName()));
                }

                source = Expression.TypeAs(source, castType);
            }

            string       propertyName          = EdmLibHelpers.GetClrPropertyName(property, _model);
            PropertyInfo propertyInfo          = source.Type.GetProperty(propertyName);
            Expression   propertyValue         = Expression.Property(source, propertyInfo);
            Type         nullablePropertyType  = TypeHelper.ToNullable(propertyValue.Type);
            Expression   nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue);

            if (filterClause != null)
            {
                bool isCollection = property.Type.IsCollection();

                IEdmTypeReference edmElementType = (isCollection ? property.Type.AsCollection().ElementType() : property.Type);
                Type clrElementType = EdmLibHelpers.GetClrType(edmElementType, _model);
                if (clrElementType == null)
                {
                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainResourceType,
                                                          edmElementType.FullName()));
                }

                Expression filterResult = nullablePropertyValue;

                ODataQuerySettings querySettings = new ODataQuerySettings()
                {
                    HandleNullPropagation = HandleNullPropagationOption.True,
                };

                if (isCollection)
                {
                    Expression filterSource = nullablePropertyValue;

                    // TODO: Implement proper support for $select/$expand after $apply
                    Expression filterPredicate = FilterBinder.Bind(null, filterClause, clrElementType, _context, querySettings);
                    filterResult = Expression.Call(
                        ExpressionHelperMethods.EnumerableWhereGeneric.MakeGenericMethod(clrElementType),
                        filterSource,
                        filterPredicate);

                    nullablePropertyType = filterResult.Type;
                }
                else if (_settings.HandleReferenceNavigationPropertyExpandFilter)
                {
                    LambdaExpression filterLambdaExpression = FilterBinder.Bind(null, filterClause, clrElementType, _context, querySettings) as LambdaExpression;
                    if (filterLambdaExpression == null)
                    {
                        throw new ODataException(Error.Format(SRResources.ExpandFilterExpressionNotLambdaExpression,
                                                              property.Name, "LambdaExpression"));
                    }

                    ParameterExpression filterParameter     = filterLambdaExpression.Parameters.First();
                    Expression          predicateExpression = new ReferenceNavigationPropertyExpandFilterVisitor(filterParameter, nullablePropertyValue).Visit(filterLambdaExpression.Body);

                    // create expression similar to: 'predicateExpression == true ? nullablePropertyValue : null'
                    filterResult = Expression.Condition(
                        test: predicateExpression,
                        ifTrue: nullablePropertyValue,
                        ifFalse: Expression.Constant(value: null, type: nullablePropertyType));
                }

                if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
                {
                    // create expression similar to: 'nullablePropertyValue == null ? null : filterResult'
                    nullablePropertyValue = Expression.Condition(
                        test: Expression.Equal(nullablePropertyValue, Expression.Constant(value: null)),
                        ifTrue: Expression.Constant(value: null, type: nullablePropertyType),
                        ifFalse: filterResult);
                }
                else
                {
                    nullablePropertyValue = filterResult;
                }
            }

            if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
            {
                // create expression similar to: 'source == null ? null : propertyValue'
                propertyValue = Expression.Condition(
                    test: Expression.Equal(source, Expression.Constant(value: null)),
                    ifTrue: Expression.Constant(value: null, type: nullablePropertyType),
                    ifFalse: nullablePropertyValue);
            }
            else
            {
                // need to cast this to nullable as EF would fail while materializing if the property is not nullable and source is null.
                propertyValue = nullablePropertyValue;
            }

            return(propertyValue);
        }
Esempio n. 21
0
        internal Expression CreatePropertyValueExpressionWithFilter(IEdmEntityType elementType, IEdmProperty property,
                                                                    Expression source, FilterClause filterClause)
        {
            Contract.Assert(elementType != null);
            Contract.Assert(property != null);
            Contract.Assert(source != null);

            IEdmEntityType declaringType = property.DeclaringType as IEdmEntityType;

            Contract.Assert(declaringType != null, "only entity types are projected.");

            // derived property using cast
            if (elementType != declaringType)
            {
                Type castType = EdmLibHelpers.GetClrType(declaringType, _model);
                if (castType == null)
                {
                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainEntityType,
                                                          declaringType.FullName()));
                }

                source = Expression.TypeAs(source, castType);
            }

            string     propertyName          = EdmLibHelpers.GetClrPropertyName(property, _model);
            Expression propertyValue         = Expression.Property(source, propertyName);
            Type       nullablePropertyType  = propertyValue.Type.ToNullable();
            Expression nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue);

            if (filterClause != null && property.Type.IsCollection())
            {
                IEdmTypeReference edmElementType = property.Type.AsCollection().ElementType();
                Type clrElementType = EdmLibHelpers.GetClrType(edmElementType, _model);
                if (clrElementType == null)
                {
                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainEntityType,
                                                          edmElementType.FullName()));
                }

                Expression filterSource =
                    typeof(IEnumerable).IsAssignableFrom(source.Type.GetProperty(propertyName).PropertyType)
                        ? Expression.Call(
                        ExpressionHelperMethods.QueryableAsQueryable.MakeGenericMethod(clrElementType),
                        nullablePropertyValue)
                        : nullablePropertyValue;

                Expression filterPredicate = FilterBinder.Bind(
                    filterClause,
                    clrElementType,
                    _model,
                    _assembliesResolver,
                    _settings);
                MethodCallExpression filterResult = Expression.Call(
                    ExpressionHelperMethods.QueryableWhereGeneric.MakeGenericMethod(clrElementType),
                    filterSource,
                    filterPredicate);

                nullablePropertyType = filterResult.Type;
                if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
                {
                    // nullablePropertyValue == null ? null : filterResult
                    nullablePropertyValue = Expression.Condition(
                        test: Expression.Equal(nullablePropertyValue, Expression.Constant(value: null)),
                        ifTrue: Expression.Constant(value: null, type: nullablePropertyType),
                        ifFalse: filterResult);
                }
                else
                {
                    nullablePropertyValue = filterResult;
                }
            }

            if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
            {
                // source == null ? null : propertyValue
                propertyValue = Expression.Condition(
                    test: Expression.Equal(source, Expression.Constant(value: null)),
                    ifTrue: Expression.Constant(value: null, type: nullablePropertyType),
                    ifFalse: nullablePropertyValue);
            }
            else
            {
                // need to cast this to nullable as EF would fail while materializing if the property is not nullable and source is null.
                propertyValue = nullablePropertyValue;
            }

            return(propertyValue);
        }
Esempio n. 22
0
        internal Expression CreatePropertyValueExpressionWithFilter(IEdmEntityType elementType, IEdmProperty property,
                                                                    Expression source, FilterClause filterClause)
        {
            Contract.Assert(elementType != null);
            Contract.Assert(property != null);
            Contract.Assert(source != null);

            IEdmEntityType declaringType = property.DeclaringType as IEdmEntityType;

            Contract.Assert(declaringType != null, "only entity types are projected.");

            // derived property using cast
            if (elementType != declaringType)
            {
                Type castType = EdmLibHelpers.GetClrType(declaringType, _model);
                if (castType == null)
                {
                    throw new ODataException("TODO: " /*Error.Format(SRResources.MappingDoesNotContainResourceType,
                                                       * declaringType.FullName())*/);
                }

                source = Expression.TypeAs(source, castType);
            }

            string     propertyName          = EdmLibHelpers.GetClrPropertyName(property, _model);
            Expression propertyValue         = Expression.Property(source, propertyName);
            Type       nullablePropertyType  = propertyValue.Type.ToNullable();
            Expression nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue);

            Type       clrElementType       = EdmLibHelpers.GetClrType(elementType, _model);
            Expression filterSource         = null;
            var        interceptorContainer = new InterceptorContainer(clrElementType, _serviceProvider);

            if ((filterClause != null || interceptorContainer.Any) && property.Type.IsCollection())
            {
                if (clrElementType == null)
                {
                    throw new ODataException("TODO:" /*Error.Format(SRResources.MappingDoesNotContainResourceType,
                                                      * edmElementType.FullName())*/);
                }

                filterSource =
                    typeof(IEnumerable).IsAssignableFrom(source.Type.GetProperty(propertyName).PropertyType)
                        ? Expression.Call(
                        ExpressionHelperMethods.QueryableAsQueryable.MakeGenericMethod(clrElementType),
                        nullablePropertyValue)
                        : nullablePropertyValue;

                Expression           filterPredicate = FilterBinder.Bind(filterClause, clrElementType, _serviceProvider);
                MethodCallExpression filterResult    = Expression.Call(
                    ExpressionHelperMethods.QueryableWhereGeneric.MakeGenericMethod(clrElementType),
                    filterSource,
                    filterPredicate);

                nullablePropertyType = filterResult.Type;
                if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
                {
                    // nullablePropertyValue == null ? null : filterResult
                    nullablePropertyValue = Expression.Condition(
                        test: Expression.Equal(nullablePropertyValue, Expression.Constant(value: null)),
                        ifTrue: Expression.Constant(value: null, type: nullablePropertyType),
                        ifFalse: filterResult);
                }
                else
                {
                    nullablePropertyValue = filterResult;
                }
            }
            if ((filterClause != null || interceptorContainer.Any) && property.Type.IsCollection())
            {
                filterSource =
                    typeof(IEnumerable).IsAssignableFrom(source.Type.GetProperty(propertyName).PropertyType)
                        ? Expression.Call(
                        ExpressionHelperMethods.QueryableAsQueryable.MakeGenericMethod(clrElementType),
                        nullablePropertyValue)
                        : nullablePropertyValue;
            }
            // TODO: Fix possibly ambiguity resolution if the
            // implementation class has multiple methods names
            // "Intercept"
            var handleNull = false;

            source = ApplyInterceptors(source, clrElementType, _serviceProvider);
            //interceptorContainer.ForEach(source, (src, predicate) =>
            //{
            //    if (filterSource != null)
            //    {
            //        // We have a collection to intercept
            //        ApplyFilterToQuery(
            //            clrElementType,
            //            filterSource,
            //            predicate,
            //            ref nullablePropertyType,
            //            ref nullablePropertyValue);
            //    }
            //    else
            //    {
            //        handleNull = true;
            //        // Apply our predicate locally
            //        nullablePropertyValue = Expression.Condition(
            //            test: Expression.Invoke(predicate, nullablePropertyValue),
            //            ifTrue: propertyValue,
            //            ifFalse: Expression.Constant(value: null, type: nullablePropertyType)
            //            );

            //        //ApplyFilterToQuery(
            //        //    clrElementType,
            //        //    propertyValue,
            //        //    predicate,
            //        //    ref nullablePropertyType,
            //        //    ref nullablePropertyValue);
            //    }
            //});

            if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
            {
                // source == null ? null : propertyValue
                propertyValue = Expression.Condition(
                    test: Expression.Equal(source, Expression.Constant(value: null)),
                    ifTrue: Expression.Constant(value: null, type: nullablePropertyType),
                    ifFalse: nullablePropertyValue);
            }
            else
            {
                // need to cast this to nullable as EF would fail while materializing if the property is not nullable and source is null.
                propertyValue = nullablePropertyValue;
            }

            return(propertyValue);
        }
Esempio n. 23
0
        private Expression CreateEntitySetAggregateExpression(
            ParameterExpression accum, EntitySetAggregateExpression expression, Type baseType)
        {
            // Should return following expression
            //  $it => $it.AsQueryable()
            //      .SelectMany($it => $it.SomeEntitySet)
            //      .GroupBy($gr => new Object())
            //      .Select($p => new DynamicTypeWrapper()
            //      {
            //          AliasOne = $p.AsQueryable().AggMethodOne($it => $it.SomePropertyOfSomeEntitySet),
            //          AliasTwo = $p.AsQueryable().AggMethodTwo($it => $it.AnotherPropertyOfSomeEntitySet),
            //          ...
            //          AliasN =  ... , // A nested expression of this same format.
            //          ...
            //      })

            List <MemberAssignment> wrapperTypeMemberAssignments = new List <MemberAssignment>();
            var        asQueryableMethod     = ExpressionHelperMethods.QueryableAsQueryable.MakeGenericMethod(baseType);
            Expression asQueryableExpression = Expression.Call(null, asQueryableMethod, accum);

            // Create lambda to access the entity set from expression
            var    source       = BindAccessor(expression.Expression.Source);
            string propertyName = EdmLibHelpers.GetClrPropertyName(expression.Expression.NavigationProperty, Model);

            var property = Expression.Property(source, propertyName);

            var baseElementType     = source.Type;
            var selectedElementType = property.Type.GenericTypeArguments.Single();

            // Create method to get property collections to aggregate
            MethodInfo selectManyMethod
                = ExpressionHelperMethods.EnumerableSelectManyGeneric.MakeGenericMethod(baseElementType, selectedElementType);

            // Create the lambda that acceses the property in the selectMany clause.
            var selectManyParam    = Expression.Parameter(baseElementType, "$it");
            var propertyExpression = Expression.Property(selectManyParam, expression.Expression.NavigationProperty.Name);
            var selectManyLambda   = Expression.Lambda(propertyExpression, selectManyParam);

            // Get expression to get collection of entities
            var entitySet = Expression.Call(null, selectManyMethod, asQueryableExpression, selectManyLambda);

            // Getting method and lambda expression of groupBy
            var        groupKeyType  = typeof(object);
            MethodInfo groupByMethod =
                ExpressionHelperMethods.EnumerableGroupByGeneric.MakeGenericMethod(selectedElementType, groupKeyType);
            var groupByLambda = Expression.Lambda(
                Expression.New(groupKeyType),
                Expression.Parameter(selectedElementType, "$gr"));

            // Group entities in a single group to apply select
            var groupedEntitySet = Expression.Call(null, groupByMethod, entitySet, groupByLambda);

            var groupingType = typeof(IGrouping <,>).MakeGenericType(groupKeyType, selectedElementType);
            ParameterExpression innerAccum = Expression.Parameter(groupingType, "$p");

            // Nested properties
            // Create dynamicTypeWrapper to encapsulate the aggregate result
            var properties = new List <NamedPropertyExpression>();

            foreach (var aggExpression in expression.Children)
            {
                properties.Add(new NamedPropertyExpression(Expression.Constant(aggExpression.Alias), CreateAggregationExpression(innerAccum, aggExpression, selectedElementType)));
            }

            var nestedResultType = typeof(EntitySetAggregationWrapper);
            var wrapperProperty  = nestedResultType.GetProperty("Container");

            wrapperTypeMemberAssignments.Add(Expression.Bind(wrapperProperty, AggregationPropertyContainer.CreateNextNamedPropertyContainer(properties)));

            var initializedMember =
                Expression.MemberInit(Expression.New(nestedResultType), wrapperTypeMemberAssignments);
            var selectLambda = Expression.Lambda(initializedMember, innerAccum);

            // Get select method
            MethodInfo selectMethod =
                ExpressionHelperMethods.EnumerableSelectGeneric.MakeGenericMethod(
                    groupingType,
                    selectLambda.Body.Type);

            return(Expression.Call(null, selectMethod, groupedEntitySet, selectLambda));
        }
        /// <summary>
        /// Creates a new instance of the backing CLR object for the given entity type.
        /// </summary>
        /// <param name="entityType">The EDM type of the entity to create.</param>
        /// <param name="readContext">The deserializer context.</param>
        /// <returns>The created CLR object.</returns>
        public virtual object CreateEntityResource(IEdmEntityTypeReference entityType, ODataDeserializerContext readContext)
        {
            if (readContext == null)
            {
                throw Error.ArgumentNull("readContext");
            }
            if (entityType == null)
            {
                throw Error.ArgumentNull("entityType");
            }

            IEdmModel model = readContext.Model;

            if (model == null)
            {
                throw Error.Argument("readContext", SRResources.ModelMissingFromReadContext);
            }

            if (readContext.IsUntyped)
            {
                return(new EdmEntityObject(entityType));
            }
            else
            {
                Type clrType = EdmLibHelpers.GetClrType(entityType, model);
                if (clrType == null)
                {
                    throw new ODataException(
                              Error.Format(SRResources.MappingDoesNotContainEntityType, entityType.FullName()));
                }

                if (readContext.IsDeltaOfT)
                {
                    IEnumerable <string> structuralProperties = entityType.StructuralProperties()
                                                                .Select(edmProperty => EdmLibHelpers.GetClrPropertyName(edmProperty, model));
                    return(Activator.CreateInstance(readContext.ResourceType, clrType, structuralProperties));
                }
                else
                {
                    return(Activator.CreateInstance(clrType));
                }
            }
        }
Esempio n. 25
0
        /// <summary>
        /// Creates a new instance of the backing CLR object for the given resource type.
        /// </summary>
        /// <param name="structuredType">The EDM type of the resource to create.</param>
        /// <param name="readContext">The deserializer context.</param>
        /// <returns>The created CLR object.</returns>
        public virtual object CreateResourceInstance(IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
        {
            if (readContext == null)
            {
                throw Error.ArgumentNull("readContext");
            }

            if (structuredType == null)
            {
                throw Error.ArgumentNull("structuredType");
            }

            IEdmModel model = readContext.Model;

            if (model == null)
            {
                throw Error.Argument("readContext", SRResources.ModelMissingFromReadContext);
            }

            if (readContext.IsUntyped)
            {
                if (structuredType.IsEntity())
                {
                    return(new EdmEntityObject(structuredType.AsEntity()));
                }

                return(new EdmComplexObject(structuredType.AsComplex()));
            }
            else
            {
                Type clrType = EdmLibHelpers.GetClrType(structuredType, model);
                if (clrType == null)
                {
                    throw new ODataException(
                              Error.Format(SRResources.MappingDoesNotContainResourceType, structuredType.FullName()));
                }

                if (readContext.IsDeltaOfT)
                {
                    IEnumerable <string> structuralProperties = structuredType.StructuralProperties()
                                                                .Select(edmProperty => EdmLibHelpers.GetClrPropertyName(edmProperty, model));

                    if (structuredType.IsOpen())
                    {
                        PropertyInfo dynamicDictionaryPropertyInfo = EdmLibHelpers.GetDynamicPropertyDictionary(
                            structuredType.StructuredDefinition(), model);

                        return(Activator.CreateInstance(readContext.ResourceType, clrType, structuralProperties,
                                                        dynamicDictionaryPropertyInfo));
                    }
                    else
                    {
                        return(Activator.CreateInstance(readContext.ResourceType, clrType, structuralProperties));
                    }
                }
                else
                {
                    return(Activator.CreateInstance(clrType));
                }
            }
        }
Esempio n. 26
0
        internal Expression CreatePropertyValueExpressionWithFilter(IEdmEntityType elementType, IEdmProperty property,
                                                                    Expression source, FilterClause filterClause)
        {
            Contract.Assert(elementType != null);
            Contract.Assert(property != null);
            Contract.Assert(source != null);

            IEdmEntityType declaringType = property.DeclaringType as IEdmEntityType;

            Contract.Assert(declaringType != null, "only entity types are projected.");

            // derived property using cast
            if (elementType != declaringType)
            {
                Type castType = EdmLibHelpers.GetClrType(declaringType, _model);
                if (castType == null)
                {
                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainResourceType,
                                                          declaringType.FullName()));
                }

                source = Expression.TypeAs(source, castType);
            }

            string     propertyName          = EdmLibHelpers.GetClrPropertyName(property, _model);
            Expression propertyValue         = Expression.Property(source, propertyName);
            Type       nullablePropertyType  = TypeHelper.ToNullable(propertyValue.Type);
            Expression nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue);

            if (filterClause != null)
            {
                bool isCollection = property.Type.IsCollection();

                IEdmTypeReference edmElementType = (isCollection ? property.Type.AsCollection().ElementType() : property.Type);
                Type clrElementType = EdmLibHelpers.GetClrType(edmElementType, _model);
                if (clrElementType == null)
                {
                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainResourceType,
                                                          edmElementType.FullName()));
                }

                Expression filterResult = nullablePropertyValue;

                ODataQuerySettings querySettings = new ODataQuerySettings()
                {
                    HandleNullPropagation = HandleNullPropagationOption.True,
                };

                if (isCollection)
                {
                    Expression filterSource =
                        typeof(IEnumerable).IsAssignableFrom(source.Type.GetProperty(propertyName).PropertyType)
                            ? Expression.Call(
                            ExpressionHelperMethods.QueryableAsQueryable.MakeGenericMethod(clrElementType),
                            nullablePropertyValue)
                            : nullablePropertyValue;

                    // TODO: Implement proper support for $select/$expand after $apply
                    Expression filterPredicate = FilterBinder.Bind(null, filterClause, clrElementType, _context, querySettings);
                    filterResult = Expression.Call(
                        ExpressionHelperMethods.QueryableWhereGeneric.MakeGenericMethod(clrElementType),
                        filterSource,
                        filterPredicate);

                    nullablePropertyType = filterResult.Type;
                }
                else if (_settings.HandleReferenceNavigationPropertyExpandFilter)
                {
                    LambdaExpression filterLambdaExpression = FilterBinder.Bind(null, filterClause, clrElementType, _context, querySettings) as LambdaExpression;
                    if (filterLambdaExpression == null)
                    {
                        throw new ODataException(Error.Format(SRResources.ExpandFilterExpressionNotLambdaExpression,
                                                              property.Name, "LambdaExpression"));
                    }

                    ParameterExpression filterParameter     = filterLambdaExpression.Parameters.First();
                    Expression          predicateExpression = new ReferenceNavigationPropertyExpandFilterVisitor(filterParameter, nullablePropertyValue).Visit(filterLambdaExpression.Body);

                    // create expression similar to: 'predicateExpression == true ? nullablePropertyValue : null'
                    filterResult = Expression.Condition(
                        test: predicateExpression,
                        ifTrue: nullablePropertyValue,
                        ifFalse: Expression.Constant(value: null, type: nullablePropertyType));
                }

                if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
                {
                    // create expression similar to: 'nullablePropertyValue == null ? null : filterResult'
                    nullablePropertyValue = Expression.Condition(
                        test: Expression.Equal(nullablePropertyValue, Expression.Constant(value: null)),
                        ifTrue: Expression.Constant(value: null, type: nullablePropertyType),
                        ifFalse: filterResult);
                }
                else
                {
                    nullablePropertyValue = filterResult;
                }
            }

            if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
            {
                // create expression similar to: 'source == null ? null : propertyValue'
                propertyValue = Expression.Condition(
                    test: Expression.Equal(source, Expression.Constant(value: null)),
                    ifTrue: Expression.Constant(value: null, type: nullablePropertyType),
                    ifFalse: nullablePropertyValue);
            }
            else
            {
                // need to cast this to nullable as EF would fail while materializing if the property is not nullable and source is null.
                propertyValue = nullablePropertyValue;
            }

            return(propertyValue);
        }
Esempio n. 27
0
        internal static void ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, object resource,
                                           ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)
        {
            IEdmProperty edmProperty;

            // Extract edmProperty using a Case-Sensitive match
            edmProperty = resourceType.FindProperty(property.Name);

            if (readContext != null && !readContext.DisableCaseInsensitiveRequestPropertyBinding && edmProperty == null)
            {
                // if edmProperty is null, we try a Case-Insensitive match.
                bool propertyMatched = false;

                IEnumerable <IEdmStructuralProperty> structuralProperties = resourceType.StructuralProperties();
                foreach (IEdmStructuralProperty structuralProperty in structuralProperties)
                {
                    if (structuralProperty.Name.Equals(property.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        // We throw an exception when we have more than 1 case-insensitive matches and no case sensitive matches.
                        if (propertyMatched)
                        {
                            throw new ODataException(Error.Format(SRResources.CannotDeserializeUnknownProperty, property.Name, resourceType.Definition));
                        }
                        propertyMatched = true;
                        edmProperty     = resourceType.FindProperty(structuralProperty.Name);
                    }
                }
            }

            bool   isDynamicProperty = false;
            string propertyName      = property.Name;

            if (edmProperty != null)
            {
                propertyName = EdmLibHelpers.GetClrPropertyName(edmProperty, readContext.Model);
            }
            else
            {
                IEdmStructuredType structuredType = resourceType.StructuredDefinition();
                isDynamicProperty = structuredType != null && structuredType.IsOpen;
            }

            if (!isDynamicProperty && edmProperty == null)
            {
                throw new ODataException(
                          Error.Format(SRResources.CannotDeserializeUnknownProperty, property.Name, resourceType.Definition));
            }

            // dynamic properties have null values
            IEdmTypeReference propertyType = edmProperty != null ? edmProperty.Type : null;

            EdmTypeKind propertyKind;
            object      value = ConvertValue(property.Value, ref propertyType, deserializerProvider, readContext,
                                             out propertyKind);

            if (isDynamicProperty)
            {
                SetDynamicProperty(resource, resourceType, propertyKind, propertyName, value, propertyType,
                                   readContext.Model);
            }
            else
            {
                SetDeclaredProperty(resource, propertyKind, propertyName, value, edmProperty, readContext);
            }
        }