示例#1
0
        private static Expression ApplyInterceptors(Expression source, Type elementType, IServiceProvider serviceProvider)
        {
            var interceptorContainer = new InterceptorContainer(elementType, serviceProvider);

            if (interceptorContainer.Any)
            {
                var parameterExpression = source as ParameterExpression;
                if (parameterExpression != null)
                {
                    source = ApplyInterceptorsToProperty(source, elementType, interceptorContainer);
                }
                var memberExpression = source as MemberExpression;
                if (memberExpression != null)
                {
                    var property = memberExpression.Member as PropertyInfo;
                    if (property == null)
                    {
                        var owningType   = memberExpression.Type.DeclaringType;
                        var propertyName = memberExpression.Member.Name;
                        property = owningType.GetProperty(propertyName);
                    }
                    source = typeof(IEnumerable).IsAssignableFrom(property.PropertyType)
                        ? ApplyInterceptorsToCollection(source, elementType, interceptorContainer)
                        : ApplyInterceptorsToProperty(source, elementType, interceptorContainer);
                }
            }
            return(source);
        }
示例#2
0
 private static Expression ApplyInterceptorsToCollection(Expression source, Type elementType,
                                                         InterceptorContainer interceptorContainer)
 {
     interceptorContainer.ForEach(source, (src, predicate) =>
     {
         var filterResult = Expression.Call(
             ExpressionHelperMethods.EnumerableWhereGeneric.MakeGenericMethod(elementType),
             src,
             predicate);
         source = filterResult;
     });
     return(source);
 }
示例#3
0
 private static Expression ApplyInterceptorsToProperty(Expression source, Type elementType,
                                                       InterceptorContainer interceptorContainer)
 {
     //return source;
     interceptorContainer.ForEach(source, (src, predicate) =>
     {
         //var m = source as MemberExpression;
         //var p = m.Member as PropertyInfo;
         ////var newExp = PredicateRewriter.RewriteLambda(predicate, src.ToString());
         //var methodCall = predicate.Body as MethodCallExpression;
         //var n = predicate.Substitute(, source);
         //var x = Expression.Lambda(predicate.Body, new[] { Expression.Parameter(m.Expression.Type) }.ToList());
         var rewrittenExpression = new ParameterReplacerVisitor(predicate.Parameters[0].Name, src).Visit(predicate.Body);
         var filterResult        = Expression.Condition(
             test: rewrittenExpression,
             ifTrue: src,
             ifFalse: Expression.Constant(elementType.GetDefault(), elementType),
             type: elementType);
         source = filterResult;
     });
     return(source);
 }
示例#4
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);
        }