Update() public method

Creates a new expression that is like this one, but using the supplied children. If all of the children are the same, it will return this expression.
public Update ( Expression left, LambdaExpression conversion, Expression right ) : BinaryExpression
left Expression The property of the result.
conversion LambdaExpression The property of the result.
right Expression The property of the result.
return BinaryExpression
Esempio n. 1
0
        protected override ExpressionTree VisitBinary(BinaryExpression node)
        {
            BinaryExpression expression;

            if (node.Conversion != null)
            {
                CheckChildrenCount(3);

                var l = ExtractChildExpression(0);
                var r = ExtractChildExpression(1);
                var c = (LambdaExpression)ExtractChildExpression(2);

                expression = node.Update(l, c, r);
            }
            else
            {
                CheckChildrenCount(2);

                var l = ExtractChildExpression(0);
                var r = ExtractChildExpression(1);

                expression = node.Update(l, conversion: null, r);
            }

            return(CreateExpressionTree(expression));
        }
Esempio n. 2
0
 /// <summary>
 /// Visits the children of the <see cref="BinaryExpression"/>.
 /// </summary>
 /// <param name="node">The expression to visit.</param>
 /// <returns>The modified expression, if it or any subexpression was modified;
 /// otherwise, returns the original expression.</returns>
 protected internal virtual Expression VisitBinary(BinaryExpression node)
 {
     // Walk children in evaluation order: left, conversion, right
     return(ValidateBinary(
                node,
                node.Update(
                    Visit(node.Left),
                    VisitAndConvert(node.Conversion, nameof(VisitBinary)),
                    Visit(node.Right)
                    )
                ));
 }
Esempio n. 3
0
            /// <summary>
            /// 替换外部字段访问为常量值
            /// </summary>
            /// <param name="node"></param>
            /// <returns></returns>
            protected override Expression VisitBinary(BinaryExpression node)
            {
                var left  = node.Left as MemberExpression;
                var right = node.Right as MemberExpression;

                if (left == null || right == null)
                {
                    return(base.VisitBinary(node));
                }

                var leftMember  = left.Member;
                var rightMember = right.Member;
                var paramType   = this.ParameterExpression.Type;

                // item=> item.Key == outInstance.Member
                if (leftMember.DeclaringType == paramType && rightMember.DeclaringType != paramType)
                {
                    var perperty = leftMember as PropertyInfo;
                    if (perperty != null)
                    {
                        var leftNode   = this.Visit(left);
                        var rightValue = Expression.Lambda(right).Compile().DynamicInvoke();
                        var rightNode  = Expression.Constant(rightValue, perperty.PropertyType);
                        return(node.Update(leftNode, node.Conversion, rightNode));
                    }
                }
                // item=> outInstance.Member == item.Key
                else if (rightMember.DeclaringType == paramType && leftMember.DeclaringType != paramType)
                {
                    var perperty = rightMember as PropertyInfo;
                    if (perperty != null)
                    {
                        var leftValue = Expression.Lambda(right).Compile().DynamicInvoke();
                        var leftNode  = Expression.Constant(leftValue, perperty.PropertyType);
                        var rightNode = this.Visit(right);
                        return(node.Update(leftNode, node.Conversion, rightNode));
                    }
                }
                return(base.VisitBinary(node));
            }
 /// <summary>
 /// Visits a binary expression that has no <see cref="BinaryExpression.Conversion"/> using the specified
 /// assignment behavior. If the node represents an assignment, the <see cref="BinaryExpression.Left"/> node
 /// is visited using <see cref="VisitLval"/>.
 /// </summary>
 /// <param name="node">The binary expression to visit.</param>
 /// <param name="isAssignment">Indicates if the node represents an assignment.</param>
 /// <returns>The result of visiting the binary expression.</returns>
 protected virtual Expression VisitBinaryWithoutConversion(BinaryExpression node, bool isAssignment)
 {
     if (isAssignment)
     {
         var left  = VisitLval(node.Left);
         var right = Visit(node.Right);
         return(node.Update(left, conversion: null, right));
     }
     else
     {
         return(base.VisitBinaryWithoutConversion(node));
     }
 }
Esempio n. 5
0
 private Expression VisitBinaryExtracted(BinaryExpression node)
 {
     return(ValidateBinary
            (
                node,
                node.Update
                (
                    Visit(node.Left),
                    node.Conversion == null ? null : VisitAndConvert(node.Conversion, nameof(VisitBinary)),
                    Visit(node.Right)
                )
            ));
 }
Esempio n. 6
0
            protected override Expression VisitBinary(BinaryExpression node)
            {
                // NB: This reduces assignment operators so that the stack spiller doesn't have to worry about it.
                if (node.CanReduce)
                {
                    return ReduceAndCheck(node);
                }

                // NB: Stack spilling of short-circuiting operators would undo the short-circuiting behavior due
                //     to evaluation of left and right for assignment into temps. We can avoid having to worry
                //     about this by reducing these nodes into more primitive conditionals and bitwise operators.
                //
                // CONSIDER: This could be moved to the stack spiller. See remarks on Reduce methods below.

                switch (node.NodeType)
                {
                    case ExpressionType.AndAlso:
                    case ExpressionType.OrElse:
                    case ExpressionType.Coalesce:
                        var hasAwait = false;

                        var left = default(Expression);
                        hasAwait |= VisitAndFindAwait(node.Left, out left);

                        var conversion = VisitAndConvert(node.Conversion, nameof(VisitBinary));

                        var right = default(Expression);
                        hasAwait |= VisitAndFindAwait(node.Right, out right);

                        var rewritten = node.Update(left, conversion, right);

                        if (hasAwait)
                        {
                            switch (node.NodeType)
                            {
                                case ExpressionType.AndAlso:
                                case ExpressionType.OrElse:
                                    return ReduceLogical(rewritten);
                                case ExpressionType.Coalesce:
                                    return ReduceCoalesce(rewritten);
                            }
                        }

                        return rewritten;
                }

                return base.VisitBinary(node);
            }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used 
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected override Expression VisitBinary(BinaryExpression node)
        {
            var newLeft = Visit(node.Left);
            var newRight = Visit(node.Right);

            if (((node.NodeType == ExpressionType.Equal)
                 || (node.NodeType == ExpressionType.NotEqual))
                && (node.Left.Type == typeof(bool))
                && (node.Right.Type == typeof(bool)))
            {
                var simpleLeft = node.Left.IsSimpleExpression();
                var simpleRight = node.Right.IsSimpleExpression();

                if (!simpleLeft
                    || !simpleRight)
                {
                    var leftOperand = simpleLeft
                        ? newLeft
                        : Expression.Condition(
                            newLeft,
                            Expression.Constant(true),
                            Expression.Constant(false),
                            typeof(bool));

                    var rightOperand = simpleRight
                        ? newRight
                        : Expression.Condition(
                            newRight,
                            Expression.Constant(true),
                            Expression.Constant(false),
                            typeof(bool));

                    return node.NodeType == ExpressionType.Equal
                        ? Expression.Equal(leftOperand, rightOperand)
                        : Expression.NotEqual(leftOperand, rightOperand);
                }
            }

            return node.Update(newLeft, node.Conversion, newRight);
        }
		protected override Expression VisitBinary(BinaryExpression node)
		{
			if (node.NodeType != ExpressionType.AndAlso && node.NodeType != ExpressionType.OrElse)
			{
				return base.VisitBinary(node);
			}

			var left = node.Left.StripQuotes();
			var right = node.Right.StripQuotes();

			if (CanMakeEqualTrueFalse(left))
			{
				left = MakeEqualTrueFalse(left);
			}

			if (CanMakeEqualTrueFalse(right))
			{
				right = MakeEqualTrueFalse(right);
			}

			return base.VisitBinary(node.Update(left, VisitAndConvert(node.Conversion, "VisitBinary"), right));
		}
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used 
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected override Expression VisitBinary(BinaryExpression node)
        {
            var newLeft = Visit(node.Left);
            var newRight = Visit(node.Right);

            if (!IsOptimalExpansion)
            {
                return node;
            }

            if ((node.NodeType == ExpressionType.Equal)
                || (node.NodeType == ExpressionType.NotEqual))
            {
                var leftIsNull = BuildIsNullExpression(newLeft);
                var rightIsNull = BuildIsNullExpression(newRight);

                var leftNullable = leftIsNull != null;
                var rightNullable = rightIsNull != null;

                if ((node.NodeType == ExpressionType.Equal)
                    && leftNullable
                    && rightNullable)
                {
                    return Expression.OrElse(
                        Expression.Equal(newLeft, newRight),
                        Expression.AndAlso(leftIsNull, rightIsNull));
                }

                if ((node.NodeType == ExpressionType.NotEqual)
                    && (leftNullable || rightNullable))
                {
                    IsOptimalExpansion = false;
                }
            }

            return node.Update(newLeft, node.Conversion, newRight);
        }
Esempio n. 10
0
            private Expression VisitBinary(BinaryExpression node, bool isAssignment)
            {
                var conversion = node.Conversion;

                //
                // Left always evaluates.
                //
                var left = isAssignment ? VisitLval(node.Left) : Visit(node.Left);

                //
                // In case we're dealing with a Coalesce node, the conversion (if any) runs on the left
                // operand provided that operand is guaranteed to be non-null.
                //
                if (!isAssignment && node.Conversion != null)
                {
                    Debug.Assert(node.NodeType == ExpressionType.Coalesce);

                    if (MayBeNull(left))
                    {
                        //
                        // We don't know if we'll end up evaluating the conversion expression, so we need
                        // to have all side-effects evaluated by now if we want to proceed.
                        //
                        if (!EnsureAllBound())
                        {
                            return(node);
                        }
                    }

                    //
                    // We got here either because left *can't* be null or because we've ensured that all
                    // side-effects have been evaluated and we still need to visit the conversion lambda
                    // to guarantee pure expressions get inlined.
                    //
                    conversion = VisitBinaryConversion(node.Conversion);
                }

                //
                // Right may or may not evaluate based on short-circuiting behavior.
                //
                if (!BinaryRightEvaluationIsGuaranteed(node, left))
                {
                    //
                    // If we're not guaranteed that right gets evaluated, we need to make sure all bindings
                    // have been satisfied.
                    //
                    if (!EnsureAllBound())
                    {
                        return(node);
                    }
                }

                //
                // Visit right regardless in order to check for duplicate bindings that may cause repetition
                // of side-effects.
                //
                var right = Visit(node.Right);

                //
                // Evaluating the binary operator may cause exceptions which may prevent subsequent evaluation
                // to take place. If this may happen, we need to ensure binding.
                //
                if (BinaryMayThrow(node) && !EnsureAllBound())
                {
                    return(node);
                }

                //
                // For assignments with conversions, the conversion is applied after the binary operator is
                // evaluated, and prior to assignment to the lhs.
                //
                if (isAssignment && node.Conversion != null)
                {
                    //
                    // The emitted code invokes the conversion lambda with a temporary holding the result of
                    // evaluating the binary operation. Thus, the evaluation of the lambda is not deferred and
                    // we can pretend the body of the lambda gets eagerly evaluated.
                    //
                    conversion = VisitBinaryConversion(node.Conversion);
                }

                return(node.Update(left, conversion, right));
            }
 protected internal virtual Expression VisitBinary(BinaryExpression node)
 {
     return(ValidateBinary(node, node.Update(this.Visit(node.Left), this.VisitAndConvert <LambdaExpression>(node.Conversion, "VisitBinary"), this.Visit(node.Right))));
 }
        protected override Expression VisitBinary(BinaryExpression node)
        {
            var children = new[] {node.Left, node.Right};

            VisitChildren(children);

            return node.Update(children[0], node.Conversion, children[1]);
        }
Esempio n. 13
0
 private BinaryExpression replaceBinaryNodeChild(BinaryExpression node, Expression oldChild, Expression newChild)
 {
     Expression leftOperand = node.Left.Equals(oldChild) ? newChild : node.Left;
     Expression rightOperand = node.Right.Equals(oldChild) ? newChild : node.Right;
     return node.Update(leftOperand, node.Conversion, rightOperand);
 }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used 
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected override Expression VisitBinary(BinaryExpression node)
        {
            var newLeft = Visit(node.Left);
            var newRight = Visit(node.Right);

            if ((node.NodeType == ExpressionType.Equal)
                || (node.NodeType == ExpressionType.NotEqual))
            {
                var leftIsNull = BuildIsNullExpression(newLeft);
                var leftNullable = leftIsNull != null;

                var rightIsNull = BuildIsNullExpression(newRight);
                var rightNullable = rightIsNull != null;

                Type conversionResultTypeLeft;
                Type conversionResultTypeRight;

                var unwrappedConvertLeft = UnwrapConvertExpression(newLeft, out conversionResultTypeLeft);
                var unwrappedConvertRight = UnwrapConvertExpression(newRight, out conversionResultTypeRight);

                var leftUnary = unwrappedConvertLeft as UnaryExpression;
                var leftNegated = (leftUnary != null) && (leftUnary.NodeType == ExpressionType.Not);

                var rightUnary = unwrappedConvertRight as UnaryExpression;
                var rightNegated = (rightUnary != null) && (rightUnary.NodeType == ExpressionType.Not);

                var leftOperand
                    = leftNegated
                        ? conversionResultTypeLeft == null
                            ? leftUnary.Operand
                            : Expression.Convert(leftUnary.Operand, conversionResultTypeLeft)
                        : newLeft;

                var rightOperand
                    = rightNegated
                        ? conversionResultTypeRight == null
                            ? rightUnary.Operand
                            : Expression.Convert(rightUnary.Operand, conversionResultTypeRight)
                        : newRight;

                if (node.NodeType == ExpressionType.Equal)
                {
                    if (leftNullable && rightNullable)
                    {
                        return leftNegated == rightNegated
                            ? ExpandNullableEqualNullable(leftOperand, rightOperand, leftIsNull, rightIsNull)
                            : ExpandNegatedNullableEqualNullable(leftOperand, rightOperand, leftIsNull, rightIsNull);
                    }

                    if (leftNullable)
                    {
                        return leftNegated == rightNegated
                            ? ExpandNullableEqualNonNullable(leftOperand, rightOperand, leftIsNull)
                            : ExpandNegatedNullableEqualNonNullable(leftOperand, rightOperand, leftIsNull);
                    }

                    if (rightNullable)
                    {
                        return leftNegated == rightNegated
                            ? ExpandNonNullableEqualNullable(leftOperand, rightOperand, rightIsNull)
                            : ExpandNegatedNonNullableEqualNullable(leftOperand, rightOperand, rightIsNull);
                    }
                }

                if (node.NodeType == ExpressionType.NotEqual)
                {
                    if (leftNullable && rightNullable)
                    {
                        return leftNegated == rightNegated
                            ? ExpandNullableNotEqualNullable(leftOperand, rightOperand, leftIsNull, rightIsNull)
                            : ExpandNegatedNullableNotEqualNullable(leftOperand, rightOperand, leftIsNull, rightIsNull);
                    }

                    if (leftNullable)
                    {
                        return leftNegated == rightNegated
                            ? ExpandNullableNotEqualNonNullable(leftOperand, rightOperand, leftIsNull)
                            : ExpandNegatedNullableNotEqualNonNullable(leftOperand, rightOperand, leftIsNull);
                    }

                    if (rightNullable)
                    {
                        return leftNegated == rightNegated
                            ? ExpandNonNullableNotEqualNullable(leftOperand, rightOperand, rightIsNull)
                            : ExpandNegatedNonNullableNotEqualNullable(leftOperand, rightOperand, rightIsNull);
                    }
                }
            }

            return node.Update(newLeft, node.Conversion, newRight);
        }
        private Expression TryOptimize(
            BinaryExpression binaryExpression,
            ExpressionType equalityType,
            Func<AliasExpression, List<Expression>, Expression> inExpressionFactory)
        {
            var leftExpression = Visit(binaryExpression.Left);
            var rightExpression = Visit(binaryExpression.Right);

            Expression leftNonColumnExpression, rightNonColumnExpression;
            IReadOnlyList<Expression> leftInValues = null;
            IReadOnlyList<Expression> rightInValues = null;

            var leftAliasExpression
                = MatchEqualityExpression(
                    leftExpression,
                    equalityType,
                    out leftNonColumnExpression);

            var rightAliasExpression
                = MatchEqualityExpression(
                    rightExpression,
                    equalityType,
                    out rightNonColumnExpression);

            if (leftAliasExpression == null)
            {
                leftAliasExpression = equalityType == ExpressionType.Equal
                    ? MatchInExpression(leftExpression, ref leftInValues)
                    : MatchNotInExpression(leftExpression, ref leftInValues);
            }

            if (rightAliasExpression == null)
            {
                rightAliasExpression = equalityType == ExpressionType.Equal
                    ? MatchInExpression(rightExpression, ref rightInValues)
                    : MatchNotInExpression(rightExpression, ref rightInValues);
            }

            if (leftAliasExpression.HasColumnExpression()
                && rightAliasExpression.HasColumnExpression()
                && leftAliasExpression.TryGetColumnExpression().Equals(rightAliasExpression.TryGetColumnExpression()))
            {
                var inArguments = new List<Expression>();
                if (leftNonColumnExpression != null)
                {
                    inArguments.Add(leftNonColumnExpression);
                }

                if (leftInValues != null)
                {
                    inArguments.AddRange(leftInValues);
                }

                if (rightNonColumnExpression != null)
                {
                    inArguments.Add(rightNonColumnExpression);
                }

                if (rightInValues != null)
                {
                    inArguments.AddRange(rightInValues);
                }

                return inExpressionFactory(
                    leftAliasExpression,
                    inArguments);
            }

            if ((leftExpression != binaryExpression.Left)
                || (rightExpression != binaryExpression.Right))
            {
                return binaryExpression.Update(leftExpression, binaryExpression.Conversion, rightExpression);
            }

            return null;
        }