/// <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)); }
/// <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); }
/// <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)); }
/// <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); }