public Expression GetGetterExpression(ParameterExpression parameterExpr) { // TODO does this keep swapping the same parameter? var replacer = new ParameterReplacerVisitor(_getterExpr.Parameters[0], parameterExpr); return(replacer.Visit(_getterExpr.Body)); }
/// <summary> /// Remaps an expression on a type to another type that have the original type as a property. /// </summary> /// <typeparam name="TTarget"></typeparam> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TResult"></typeparam> /// <param name="source"></param> /// <param name="selector"></param> /// <returns></returns> public static Expression <Func <TTarget, TResult> > RemapTo <TTarget, TSource, TResult>(this Expression <Func <TSource, TResult> > source, Expression <Func <TTarget, TSource> > selector) { var map = new Dictionary <ParameterExpression, Expression> { [source.Parameters.Single()] = selector.Body }; var resultBody = new ParameterReplacerVisitor(map).Visit(source.Body); return(Expression.Lambda <Func <TTarget, TResult> >(resultBody, selector.Parameters)); }
/// <summary>Replaced the type of input parameter with the given <paramref name="targetType"/></summary> /// <param name="input">Input lambda expression.</param> /// <param name="targetType">Type of the new parameter that will be replaced.</param> /// <returns>New lambda expression with parameter of new type.</returns> private static LambdaExpression ReplaceParameterTypeForLambda(LambdaExpression input, Type targetType) { Debug.Assert(input.Parameters.Count == 1, "Assuming a single parameter for input lambda expression in this function."); ParameterExpression p = Expression.Parameter(targetType, input.Parameters[0].Name); return(Expression.Lambda( ParameterReplacerVisitor.Replace(input.Body, input.Parameters[0], p), p)); }
public static Expression <TFunc> Merge <TFunc>( this Expression <TFunc> left, Expression <TFunc> right, Func <Expression, Expression, Expression> merge) { var parametersMap = left.Parameters .Select((param, index) => new { r = right.Parameters[index], l = param }) .ToDictionary(x => x.r, x => x.l); var rightBody = new ParameterReplacerVisitor(parametersMap).Visit(right.Body); return(Expression.Lambda <TFunc>(merge(left.Body, rightBody), left.Parameters)); }
public static Expression <Func <T, bool> > And <T>(this Expression <Func <T, bool> > left, Expression <Func <T, bool> > right) { var p1 = left.Parameters.First(); var p2 = right.Parameters.First(); if (p1.Name != p2.Name) { var replacer = new ParameterReplacerVisitor <Func <T, bool> >(p1); right = replacer.VisitAndConvert(right); } var newBody = Expression.AndAlso(left.Body, right.Body); return(Expression.Lambda <Func <T, bool> >(newBody, left.Parameters)); }
private static Expression <T> Combine <T>(this Expression <T> first, Expression <T> second, Func <Expression, Expression, BinaryExpression> operatorFunc) { if (first == null || second == null) { return(first ?? second); } var map = second.Parameters .Zip(first.Parameters, (key, value) => new { key, value }) .ToDictionary(x => x.key, x => (Expression)x.value); var secondBody = new ParameterReplacerVisitor(map).Visit(second.Body); return(Expression.Lambda <T>(operatorFunc(first.Body, secondBody), first.Parameters)); }
/// <summary>Composes all query interceptors into a single expression.</summary> /// <param name="serviceInstance">Web service instance.</param> /// <param name="container">Container for which interceptors should run.</param> /// <returns>An expression the filter for query interceptors, possibly null.</returns> internal static Expression ComposeQueryInterceptors(object serviceInstance, ResourceSetWrapper container) { Debug.Assert(container != null, "container != null"); MethodInfo[] methods = container.QueryInterceptors; if (methods == null || methods.Length == 0) { return(null); } LambdaExpression filter = null; for (int i = 0; i < methods.Length; i++) { Expression predicate; try { predicate = (Expression)methods[i].Invoke(serviceInstance, WebUtil.EmptyObjectArray); } catch (TargetInvocationException tie) { ErrorHandler.HandleTargetInvocationException(tie); throw; } if (predicate == null) { throw new InvalidOperationException(Strings.DataService_AuthorizationReturnedNullQuery(methods[i].Name, methods[i].DeclaringType.FullName)); } // predicate is LambdaExpression -- otherwise signature check missed something and following cast would throw LambdaExpression lambdaPredicate = ((LambdaExpression)predicate); if (filter == null) { filter = lambdaPredicate; } else { ParameterExpression parameter = filter.Parameters[0]; Expression adjustedPredicate = ParameterReplacerVisitor.Replace( lambdaPredicate.Body, // expression lambdaPredicate.Parameters[0], // oldParameter parameter); // newParameter filter = Expression.Lambda(Expression.And(filter.Body, adjustedPredicate), parameter); } } return(filter); }
public bool TryParse(PrioritizedString expr, ParameterInfo paramInfo, out Expression parsed) { var minPriorityInds = expr.Priorities.GetMinIndexes(); var whereParts = expr.SplitOnSubset("where", minPriorityInds); if (whereParts.Length > 2) { throw new ParseException("Too many 'where'!"); } if (whereParts.Length == 1) { parsed = null; return(false); } var mainFunc = whereParts[0]; if (mainFunc.Input.Last() == ',') { mainFunc = mainFunc.Substring(0, mainFunc.Input.Length - 1); } var parameterExpressions = new Dictionary <string, PrioritizedString>(); foreach (Match match in ParameterRe.Matches(whereParts[1].Input)) { var(paramName, paramExpr) = (match.Groups["paramName"].Value, match.Groups["paramExpr"].Value); if (paramInfo.Parameters.ContainsKey(paramName)) { throw new ParseException($"Parameter {paramName} is defined multiple times"); } paramInfo.Parameters[paramName] = Expression.Parameter(typeof(double), paramName); parameterExpressions[paramName] = new PrioritizedString(paramExpr); } var parameterExprs = parameterExpressions .ToDictionary( nameWithExpr => nameWithExpr.Key, nameWithExpr => Combinator.ParseFunctionalExpression(nameWithExpr.Value, paramInfo) ); var mainExpr = Combinator.ParseFunctionalExpression(mainFunc, paramInfo); var paramReplacer = new ParameterReplacerVisitor(parameterExprs); parsed = paramReplacer.Visit(mainExpr); return(true); }
IQueryable <T> IQuery <T> .Execute(Expression <Func <T, bool> > predicate) { var modifiedPredicate = predicate; var filterExpression = _context.GetContextFilterExpression <T>(); if (filterExpression != null) { var typeParam = predicate.Parameters[0]; var filter = new ParameterReplacerVisitor(typeParam).Visit(filterExpression.Body); modifiedPredicate = Expression.Lambda <Func <T, bool> >(Expression.AndAlso(predicate.Body, filter), typeParam); } return(((IQuery <T>)_crud).Execute(modifiedPredicate)); }
public static Expression <Func <T, TResult> > Chain <T, TIntermediate, TResult>(this Expression <Func <T, TIntermediate> > expression, Expression <Func <TIntermediate, TResult> > otherExpression) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (otherExpression == null) { throw new ArgumentNullException(nameof(otherExpression)); } var paramReplacer = new ParameterReplacerVisitor(expression); return((Expression <Func <T, TResult> >)paramReplacer.Visit(otherExpression)); }
public EquatableExpression(LambdaExpression expression) { if (expression == null) { throw new ArgumentNullException("expression"); } if (expression.Parameters.Count != 1) { throw new ArgumentException("Invalid LambdaExpression. Must only have one parameter."); } _expression = expression; _parameterType = _expression.Parameters[0].Type; var visitor = new ParameterReplacerVisitor(); _expressionAsString = visitor.Visit(expression).ToString(); }
public void ParametersReplacer_Test() { var args = new Dictionary <string, ConstantExpression> { ["a"] = Expression.Constant(4), ["b"] = Expression.Constant(1), }; Expression <Func <int, int, int, int> > source_exp = (a, b, c) => c + (a - 1) * b + (a + 1) * (a + 5) * (a + 1); var result_exp = new ParameterReplacerVisitor(args).VisitAndConvert(source_exp, ""); Console.WriteLine(source_exp + " " + source_exp.Compile().Invoke(3, 3, 2)); Console.WriteLine(result_exp + " " + result_exp.Compile().Invoke(3, 3, 2)); Console.WriteLine("Source Expression:"); new TraceExpressionVisitor().Visit(source_exp); Console.WriteLine("Result Expression:"); new TraceExpressionVisitor().Visit(result_exp); }
/// <summary> /// Composes a property navigation with the appropriate filter lamba, as appropriate. /// </summary> /// <param name="expression">Member access expression to compose.</param> /// <param name="filterLambda">Lambda expression used for the filter.</param> /// <param name="propagateNull">Whether null propagation is required on the <paramref name="expression"/>.</param> /// <param name="isSingleResult">Whether <paramref name="expression"/> represent a single resource navigation.</param> /// <returns>The composed expression.</returns> internal static Expression ComposePropertyNavigation( Expression expression, LambdaExpression filterLambda, bool propagateNull, bool isSingleResult) { Debug.Assert(expression != null, "expression != null"); Debug.Assert(filterLambda != null, "filterLambda != null"); Expression nullConstant = NullLiteral; if (isSingleResult) { Expression fixedFilter = ParameterReplacerVisitor.Replace( filterLambda.Body, filterLambda.Parameters[0], expression); Expression test = propagateNull ? Expression.AndAlso(Expression.NotEqual(expression, nullConstant), fixedFilter) : fixedFilter; Expression conditionTrue = expression; Expression conditionFalse = Expression.Constant(null, conditionTrue.Type); return(Expression.Condition(test, conditionTrue, conditionFalse)); } Type elementType = filterLambda.Parameters[0].Type; Expression filterExpression = expression.EnumerableWhere(filterLambda); if (propagateNull) { Expression test = Expression.Equal(expression, nullConstant); Expression falseIf = filterExpression; Expression trueIf = EnumerableEmpty(elementType); return(Expression.Condition(test, trueIf, falseIf, trueIf.Type)); } return(filterExpression); }
/// <summary>Makes the expression that is used as a filter corresponding to skip token.</summary> /// <param name="topLevelOrderingInfo">Ordering expression.</param> /// <param name="skipToken">The provided skip token.</param> /// <param name="parameterType">The parameter type of the lambda.</param> /// <returns>LambdaExpression corresponding to the skip token filter.</returns> internal LambdaExpression BuildSkipTokenFilter(OrderingInfo topLevelOrderingInfo, IList <object> skipToken, Type parameterType) { ParameterExpression element = Expression.Parameter(parameterType, "element"); Expression lastCondition = Expression.Constant(true, typeof(bool)); Expression lastMatch = Expression.Constant(false, typeof(bool)); foreach (var v in WebUtil.Zip(topLevelOrderingInfo.OrderingExpressions, skipToken, (x, y) => new { Order = x, Value = y })) { BinaryOperatorKind comparisonExp = v.Order.IsAscending ? BinaryOperatorKind.GreaterThan : BinaryOperatorKind.LessThan; Expression fixedLambda = ParameterReplacerVisitor.Replace( ((LambdaExpression)v.Order.Expression).Body, ((LambdaExpression)v.Order.Expression).Parameters[0], element); // TODO: this will be an EnumNode if $skiptoken contains enum constant. ConstantNode node; var lexer = new ExpressionLexer((string)v.Value); bool success = TokenToQueryNodeTranslator.TryCreateLiteral(lexer.CurrentToken, out node); Debug.Assert(success, "Was not a literal"); node = this.EnsureCorrectTypeAndPrecisionForLFDM(node, fixedLambda.Type); Expression right = this.nodeToExpressionTranslator.TranslateNode(node); Expression comparison = ExpressionGenerator.GenerateLogicalAnd( lastCondition, this.GenerateNullAwareComparison(fixedLambda, right, comparisonExp)); lastMatch = ExpressionGenerator.GenerateLogicalOr(lastMatch, comparison); lastCondition = ExpressionGenerator.GenerateLogicalAnd( lastCondition, this.GenerateComparisonExpression(fixedLambda, right, BinaryOperatorKind.Equal)); } lastMatch = ExpressionUtils.EnsurePredicateExpressionIsBoolean(lastMatch); Debug.Assert(lastMatch.Type == typeof(bool), "Skip token should generate boolean expression."); return(Expression.Lambda(lastMatch, element)); }
internal static Expression <Func <TItem, bool> > CombinePredicates <TItem>(IEnumerable <Expression <Func <TItem, bool> > > predicates) { ParameterExpression paramExpr = null; Expression combinedPredicate = null; foreach (Expression <Func <TItem, bool> > predicate in predicates) { if (predicate == null) { continue; } Expression predicateBody; if (paramExpr == null) { paramExpr = predicate.Parameters[0]; predicateBody = predicate.Body; } else { var visitor = new ParameterReplacerVisitor(predicate.Parameters[0], paramExpr); predicateBody = visitor.Visit(predicate.Body); } combinedPredicate = combinedPredicate == null ? predicateBody : Expression.OrElse(combinedPredicate, predicateBody); } if (combinedPredicate == null) { return(item => false); } var combinedLambda = Expression.Lambda <Func <TItem, bool> >(combinedPredicate, paramExpr); return(combinedLambda); }
private PredicateBuilder(bool value) { _param = Expression.Parameter(typeof(T)); _paramReplacer = new ParameterReplacerVisitor(_param); _body = Expression.Constant(value); }
public Expression GetSelectExpression(ParameterExpression itemPram) { var replacer = new ParameterReplacerVisitor(_middleExpression.Parameters[0], itemPram); return(replacer.Visit(_middleExpression.Body)); }
protected override Expression GetGetterExpression(ParameterExpression parameterExpr) { var replacer = new ParameterReplacerVisitor(_getterExpression.Parameters[0], parameterExpr); return(replacer.Visit(_getterExpression.Body)); }