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)); }
/// <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); }
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))); }
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)); }
/// <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)); }
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)); }
/// <summary> /// An Expression<Func<T,bool>> 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<Func<T,bool>></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])); }
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)); }
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)); }
/// <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); }
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); }
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); }
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)); }
/// <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)); }
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); }
private static Expression GetValueExpression(Expression valueExpression, ParameterExpression parameter) { valueExpression = new ReplaceParameterVisitor(parameter).Visit(valueExpression); return(valueExpression); }