コード例 #1
0
        public MemberExpression GetJoinPropertyExpression(Expression source, Expression parameter, SingleValuePropertyAccessNode propertyNode)
        {
            IReadOnlyList <IEdmNavigationProperty> joinPath = GetJoinPath(propertyNode);
            MemberExpression propertyExpression             = GetJoinPropertyExpression(source, parameter, joinPath, propertyNode.Property);

            if (propertyExpression != null)
            {
                return(propertyExpression);
            }

            propertyExpression = (MemberExpression)Visitor.TranslateNode(propertyNode);
            if (propertyExpression == null)
            {
                throw new InvalidOperationException("property " + propertyNode.Property.Name + " not found");
            }

            if (Visitor.Parameter == parameter)
            {
                return(propertyExpression);
            }

            var replaceParameterVisitor = new ReplaceParameterVisitor(Visitor.Parameter, parameter);

            return((MemberExpression)replaceParameterVisitor.Visit(propertyExpression));
        }
コード例 #2
0
        /// <summary>
        /// Replaces the parameter of the expression with given one.
        /// </summary>
        /// <typeparam name="T">Type the expression is being used on.</typeparam>
        /// <param name="expression">Expression to be changed.</param>
        /// <param name="parameter">Parameter for the new expression.</param>
        /// <returns>The expression with the new parameter.</returns>
        private static Expression ReplaceParameter <T>(Expression <Func <T, bool> > expression, ParameterExpression parameter)
        {
            var visitor       = new ReplaceParameterVisitor(expression.Parameters[0], parameter);
            var newexpression = visitor.Visit(expression.Body);

            return(newexpression);
        }
コード例 #3
0
        public MethodCallExpression Build(Expression outer, Expression inner, ODataPath odataPath, OrderByClause orderBy, long?skip, long?top)
        {
            var segment = (NavigationPropertySegment)odataPath.LastSegment;
            IEdmNavigationProperty navigationProperty = segment.NavigationProperty;

            if (navigationProperty.ContainsTarget)
            {
                ModelBuilder.ManyToManyJoinDescription joinDescription = _edmModel.GetManyToManyJoinDescription(navigationProperty);
                IEdmEntitySet joinEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, joinDescription.JoinNavigationProperty);
                outer = OeEnumerableStub.CreateEnumerableStubExpression(joinDescription.JoinClassType, joinEntitySet);
                navigationProperty = joinDescription.TargetNavigationProperty;
            }

            Type outerType = OeExpressionHelper.GetCollectionItemType(outer.Type);
            ParameterExpression outerParameter = Expression.Parameter(outerType, outerType.Name);

            inner = new ReplaceParameterVisitor(outerParameter).Visit(inner); //replace $it
            Expression subquery = CreateWhereExpression(outerParameter, inner, navigationProperty);

            subquery = _expressionBuilder.ApplyOrderBy(subquery, orderBy);
            subquery = _expressionBuilder.ApplySkip(subquery, skip, odataPath);
            subquery = _expressionBuilder.ApplyTake(subquery, top, odataPath);

            Type       innerType            = OeExpressionHelper.GetCollectionItemType(inner.Type);
            MethodInfo selectManyMethdoInfo = OeMethodInfoHelper.GetSelectManyMethodInfo(outerType, innerType);

            return(Expression.Call(selectManyMethdoInfo, outer, Expression.Lambda(subquery, outerParameter)));
        }
コード例 #4
0
        public static Expression <Func <T, bool> > AndAlso <T>(this Expression <Func <T, bool> > expr1, Expression <Func <T, bool> > expr2)
        {
            ParameterExpression parameter1 = expr1.Parameters[0];
            var visitor         = new ReplaceParameterVisitor(expr2.Parameters[0], parameter1);
            var body2WithParam1 = visitor.Visit(expr2.Body);

            return(Expression.Lambda <Func <T, bool> >(Expression.AndAlso(expr1.Body, body2WithParam1), parameter1));
        }
コード例 #5
0
        /// <summary>
        /// Returns a new expression where references to the specified parameter
        /// have been replaced by references to another one.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="original">The original parameter.</param>
        /// <param name="replacement">The replacement parameter.</param>
        /// <returns></returns>
        public static Expression ReplaceParameter(
            this Expression expression,
            ParameterExpression original,
            Expression replacement
            )
        {
            var visitor = new ReplaceParameterVisitor(original, replacement);

            return(visitor.Visit(expression));
        }
コード例 #6
0
    public static Expression <Func <T, bool> > Or <T>(this Expression <Func <T, bool> > one, Expression <Func <T, bool> > another)
    {
        var parameter = one.Parameters[0];
        var visitor   = new ReplaceParameterVisitor(parameter);

        another = (Expression <Func <T, bool> >)visitor.Visit(another);
        var body = Expression.Or(one.Body, another.Body);

        return(Expression.Lambda <Func <T, bool> >(body, parameter));
    }
コード例 #7
0
        /// <summary>
        /// An Expression&lt;Func&lt;T,bool&gt;&gt; extension method that with parameters of.
        /// </summary>
        /// <typeparam name="T">Generic type parameter.</typeparam>
        /// <param name="left">The left.</param>
        /// <param name="right">The right.</param>
        /// <param name="expressionType">Type of the expression.</param>
        /// <returns>An Expression&lt;Func&lt;T,bool&gt;&gt;</returns>
        private static Expression <Func <T, bool> > WithParametersOf <T>(this Expression <Func <T, bool> > left,
                                                                         Expression <Func <T, bool> > right, ExpressionType expressionType)
        {
            var visitor = new ReplaceParameterVisitor {
                SubstituteMapping = { [right.Parameters[0]] = left.Parameters[0] }
            };

            Expression body = Expression.MakeBinary(expressionType, left.Body, visitor.Visit(right.Body));

            return(Expression.Lambda <Func <T, bool> >(body, left.Parameters[0]));
        }
コード例 #8
0
        public static Expression <T> AddExpression <T>(this Expression <T> first, Expression <T> second, Func <Expression, Expression, Expression> merge)
        {
            var map = first.Parameters.Select((left, i) => new
            {
                left,
                right = second.Parameters[i]
            }).ToDictionary(p => p.right, p => p.left);

            var rightBody = ReplaceParameterVisitor.ReplacementExpression(map, second.Body);

            return(Expression.Lambda <T>(merge(first.Body, rightBody), first.Parameters));
        }
コード例 #9
0
        public static Expression <Func <T, bool> > Combine <T>(Expression <Func <T, bool> > leftExpression, Expression <Func <T, bool> > rightExpression, Func <Expression, Expression, BinaryExpression> combineOperator)
        {
            var leftParameter  = leftExpression.Parameters[0];
            var rightParameter = rightExpression.Parameters[0];

            var visitor = new ReplaceParameterVisitor(rightParameter, leftParameter);

            var leftBody  = leftExpression.Body;
            var rightBody = visitor.Visit(rightExpression.Body);

            return(Expression.Lambda <Func <T, bool> >(combineOperator(leftBody, rightBody), leftParameter));
        }
コード例 #10
0
        /// <summary>
        /// Returns a new expression where references to the specified parameter
        /// have been replaced by references to another one.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="original">The original parameter.</param>
        /// <param name="replacement">The replacement parameter.</param>
        /// <param name="wasReplaced">Indicates whether the <paramref name="original"/> has been replaced at least once.</param>
        /// <returns></returns>
        public static Expression ReplaceParameter(
            this Expression expression,
            ParameterExpression original,
            Expression replacement,
            out bool wasReplaced
            )
        {
            var visitor = new ReplaceParameterVisitor(original, replacement);
            var result  = visitor.Visit(expression);

            wasReplaced = visitor.WasReplaced;
            return(result);
        }
コード例 #11
0
        public static MemberExpression GetPropertyExpression(OeJoinBuilder joinBuilder, Expression source, Expression parameterExpression, SingleValueNode sortProperty)
        {
            if (sortProperty is SingleValuePropertyAccessNode propertyNode)
            {
                return(joinBuilder.GetJoinPropertyExpression(source, parameterExpression, propertyNode));
            }

            if (sortProperty is SingleValueOpenPropertyAccessNode openPropertyNode)
            {
                var propertyExpression      = (MemberExpression)joinBuilder.Visitor.TranslateNode(openPropertyNode);
                var replaceParameterVisitor = new ReplaceParameterVisitor(joinBuilder.Visitor.Parameter, parameterExpression);
                return((MemberExpression)replaceParameterVisitor.Visit(propertyExpression));
            }

            throw new InvalidOperationException("Unknown type order by expression " + sortProperty.GetType().Name);
        }
コード例 #12
0
    public static Expression <Func <TElement, bool> > ReplaceParameter <TElement>(
        Expression <Func <TElement, TElement, bool> > inputExpression,
        TElement element)
    {
        Expression body = inputExpression.Body;
        ReplaceParameterVisitor visitor =
            new ReplaceParameterVisitor(inputExpression.Parameters[1],
                                        Expression.Constant(element, typeof(TElement)));
        Expression newBody = visitor.Visit(body);
        Expression <Func <TElement, bool> > newExpression =
            Expression.Lambda <Func <TElement, Boolean> >(
                newBody,
                new ParameterExpression[] { inputExpression.Parameters[0] });

        return(newExpression);
    }
コード例 #13
0
        public MemberExpression GetJoinPropertyExpression(Expression source, Expression parameter, SingleValuePropertyAccessNode propertyNode)
        {
            IReadOnlyList <IEdmNavigationProperty> joinPath = GetJoinPath(propertyNode);
            MemberExpression?joinPropertyExpression         = GetJoinPropertyExpression(source, parameter, joinPath, propertyNode.Property);

            if (joinPropertyExpression != null)
            {
                return(joinPropertyExpression);
            }

            var propertyExpression = (MemberExpression)Visitor.TranslateNode(propertyNode);

            if (Visitor.Parameter == parameter)
            {
                return(propertyExpression);
            }

            var replaceParameterVisitor = new ReplaceParameterVisitor(Visitor.Parameter, parameter);

            return((MemberExpression)replaceParameterVisitor.Visit(propertyExpression));
        }
コード例 #14
0
        /// <summary>
        /// Replace parameter <paramref name="oldExpression"/> by <paramref name="newExpression"/>.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="oldExpression">The parameter to be replaced.</param>
        /// <param name="newExpression">The expression to replace all occurrences of <paramref name="oldExpression"/>.</param>
        /// <returns>New expression with applied replacement.</returns>
        public static Expression ReplaceParameter(
            this Expression expression,
            ParameterExpression oldExpression,
            Expression newExpression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            if (oldExpression == null)
            {
                throw new ArgumentNullException(nameof(oldExpression));
            }

            if (newExpression == null)
            {
                throw new ArgumentNullException(nameof(newExpression));
            }

            var visitor = new ReplaceParameterVisitor(oldExpression, newExpression);

            return(visitor.Visit(expression));
        }
コード例 #15
0
        private static Expression SelectStructuralProperties(Expression source, OeNavigationSelectItem root)
        {
            if (!root.HasNavigationItems())
            {
                return(source);
            }

            ParameterExpression parameter          = Expression.Parameter(OeExpressionHelper.GetCollectionItemType(source.Type));
            IReadOnlyList <MemberExpression> joins = OeExpressionHelper.GetPropertyExpressions(parameter);
            var newJoins = new Expression[joins.Count];

            List <OeNavigationSelectItem> navigationItems = FlattenNavigationItems(root, false);
            bool isNavigationNullable = false;

            for (int i = 0; i < navigationItems.Count; i++)
            {
                newJoins[i]           = joins[i];
                isNavigationNullable |= i > 0 && navigationItems[i].EdmProperty.Type.IsNullable;
                if (!navigationItems[i].AllSelected)
                {
                    IReadOnlyList <OeStructuralSelectItem> structuralItems = navigationItems[i].GetStructuralItemsWithNotSelected();
                    if (structuralItems.Count > 0)
                    {
                        var properties = new Expression[structuralItems.Count];
                        for (int j = 0; j < structuralItems.Count; j++)
                        {
                            if (structuralItems[j].EdmProperty is ComputeProperty computeProperty)
                            {
                                properties[j] = new ReplaceParameterVisitor(joins[i]).Visit(computeProperty.Expression);
                            }
                            else
                            {
                                PropertyInfo property = joins[i].Type.GetPropertyIgnoreCase(structuralItems[j].EdmProperty);
                                properties[j] = Expression.Property(joins[i], property);
                            }
                        }
                        Expression newTupleExpression = OeExpressionHelper.CreateTupleExpression(properties);

                        if (isNavigationNullable)
                        {
                            UnaryExpression nullConstant = Expression.Convert(OeConstantToVariableVisitor.NullConstantExpression, newTupleExpression.Type);
                            newTupleExpression = Expression.Condition(Expression.Equal(joins[i], OeConstantToVariableVisitor.NullConstantExpression), nullConstant, newTupleExpression);
                        }
                        newJoins[i] = newTupleExpression;
                    }
                }
            }

            NewExpression    newSelectorBody  = OeExpressionHelper.CreateTupleExpression(newJoins);
            MethodInfo       selectMethodInfo = OeMethodInfoHelper.GetSelectMethodInfo(parameter.Type, newSelectorBody.Type);
            LambdaExpression newSelector      = Expression.Lambda(newSelectorBody, parameter);

            //Quirk EF Core 2.1.1 bug Take/Skip must be last in expression tree
            var skipTakeExpressions = new List <MethodCallExpression>();

            while (source is MethodCallExpression callExpression && (callExpression.Method.Name == nameof(Enumerable.Skip) || callExpression.Method.Name == nameof(Enumerable.Take)))
            {
                skipTakeExpressions.Add(callExpression);
                source = callExpression.Arguments[0];
            }

            source = Expression.Call(selectMethodInfo, source, newSelector);

            for (int i = skipTakeExpressions.Count - 1; i >= 0; i--)
            {
                MethodInfo skipTakeMethodInfo = skipTakeExpressions[i].Method.GetGenericMethodDefinition().MakeGenericMethod(newSelector.ReturnType);
                source = Expression.Call(skipTakeMethodInfo, source, skipTakeExpressions[i].Arguments[1]);
            }

            return(source);
        }
コード例 #16
0
 private static Expression GetValueExpression(Expression valueExpression,
                                              ParameterExpression parameter)
 {
     valueExpression = new ReplaceParameterVisitor(parameter).Visit(valueExpression);
     return(valueExpression);
 }