public Update ( |
||
left | The |
|
conversion | The |
|
right | The |
|
return |
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)); }
/// <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) ) )); }
/// <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)); } }
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) ) )); }
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); }
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]); }
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; }