/// <summary> /// Apply orderby to the given resouce expression /// </summary> /// <param name="rootExpression"></param> /// <param name="entityInstanceType"></param> /// <param name="uriParser"></param> /// <param name="orderByClause"></param> /// <returns></returns> public static Expression ApplyOrderBy(this Expression rootExpression, Type entityInstanceType, ODataUriParser uriParser, OrderByClause orderByClause) { ParameterExpression parameter = Expression.Parameter(entityInstanceType, "it"); NodeToExpressionTranslator nodeToExpressionTranslator = new NodeToExpressionTranslator() { ImplicitVariableParameterExpression = parameter, UriParser = uriParser, }; Expression orderByNodeExpression = nodeToExpressionTranslator.TranslateNode(orderByClause.Expression); var keyType = EdmClrTypeUtils.GetInstanceType(orderByClause.Expression.TypeReference); if (orderByClause.Expression.TypeReference.IsNullable && keyType.IsValueType) { keyType = typeof(Nullable <>).MakeGenericType(keyType); } var method = orderByClause.Direction == OrderByDirection.Ascending ? "OrderBy" : "OrderByDescending"; //OrderBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector) var expression = Expression.Call( typeof(Enumerable), method, new Type[] { entityInstanceType, keyType }, rootExpression, Expression.Lambda(orderByNodeExpression, parameter)) as Expression; var thenBy = orderByClause.ThenBy; while (null != thenBy) { expression = expression.ApplyThenBy(entityInstanceType, uriParser, thenBy); thenBy = thenBy.ThenBy; } return(expression); }
/// <summary> /// Apply filter to the given resouce expression /// </summary> /// <param name="rootExpression"></param> /// <param name="entityInstanceType"></param> /// <param name="uriParser"></param> /// <param name="filterClause"></param> /// <returns></returns> public static Expression ApplyFilter(this Expression rootExpression, Type entityInstanceType, ODataUriParser uriParser, FilterClause filterClause) { ParameterExpression parameter = Expression.Parameter(entityInstanceType, "it"); NodeToExpressionTranslator nodeToExpressionTranslator = new NodeToExpressionTranslator() { ImplicitVariableParameterExpression = parameter, UriParser = uriParser, }; Expression filterNodeExpression = nodeToExpressionTranslator.TranslateNode(filterClause.Expression); // IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate); // translate to rootExpression.Where(filterNodeExpression) return(Expression.Call( typeof(Enumerable), "Where", new Type[] { entityInstanceType }, rootExpression, Expression.Lambda(filterNodeExpression, parameter))); }
/// <summary> /// Visit an AnyNode /// </summary> /// <param name="nodeIn">The node to visit</param> /// <returns>The translated expression</returns> public override Expression Visit(AnyNode nodeIn) { var instanceType = EdmClrTypeUtils.GetInstanceType(nodeIn.RangeVariables[0].TypeReference); ParameterExpression parameter = Expression.Parameter(instanceType, nodeIn.RangeVariables[0].Name); NodeToExpressionTranslator nodeToExpressionTranslator = new NodeToExpressionTranslator() { ImplicitVariableParameterExpression = parameter, UriParser = this.UriParser, DataSource = this.DataSource, }; Expression conditionExpression = nodeToExpressionTranslator.TranslateNode(nodeIn.Body); Expression rootExpression = this.TranslateNode(nodeIn.Source); return(Expression.Call( typeof(Enumerable), "Any", new Type[] { instanceType }, rootExpression, Expression.Lambda(conditionExpression, parameter))); }
/// <summary> /// Apply thenOrderBy to the given resouce expression /// </summary> /// <param name="rootExpression"></param> /// <param name="entityInstanceType"></param> /// <param name="uriParser"></param> /// <param name="thenBy"></param> /// <returns></returns> public static Expression ApplyThenBy(this Expression rootExpression, Type entityInstanceType, ODataUriParser uriParser, OrderByClause thenBy) { ParameterExpression parameter = Expression.Parameter(entityInstanceType, "it"); NodeToExpressionTranslator nodeToExpressionTranslator = new NodeToExpressionTranslator() { ImplicitVariableParameterExpression = parameter, UriParser = uriParser, }; Expression orderByNodeExpression = nodeToExpressionTranslator.TranslateNode(thenBy.Expression); var keyType = EdmClrTypeUtils.GetInstanceType(thenBy.Expression.TypeReference); var method = thenBy.Direction == OrderByDirection.Ascending ? "ThenBy" : "ThenByDescending"; //ThenBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector) return(Expression.Call( typeof(Enumerable), method, new Type[] { entityInstanceType, keyType }, rootExpression, Expression.Lambda(orderByNodeExpression, parameter))); }
/// <summary> /// Translate OperationSegment to linq expression. /// </summary> /// <param name="segment">The OperationSegment</param> /// <returns>The linq expression</returns> public override Expression Translate(OperationSegment segment) { IEdmOperation operation = segment.Operations.First(); List <Expression> arguments = new List <Expression>(); if (operation.IsBound) { arguments.Add(this.ResultExpression); } if (operation is IEdmFunction) { NodeToExpressionTranslator nodeToExpressionTranslator = new NodeToExpressionTranslator() { UriParser = this.queryContext.UriParser, DataSource = this.dataSource, }; arguments.AddRange(segment.Parameters.Select(p => nodeToExpressionTranslator.TranslateNode((QueryNode)p.Value))); var operationProvider = this.dataSource.OperationProvider; operationProvider.QueryContext = this.queryContext; this.ResultExpression = Expression.Call(Expression.Constant(operationProvider), operation.Name, new Type[] { }, arguments.ToArray()); } else if (operation is IEdmAction) { arguments.AddRange(this.ActionInvokeParameters); var operationProvider = this.dataSource.OperationProvider; operationProvider.QueryContext = this.queryContext; this.ResultExpression = Expression.Call(Expression.Constant(operationProvider), operation.Name, new Type[] { }, arguments.ToArray()); } else { throw new NotImplementedException("Unsupported operation type."); } this.LastProcessedSegment = segment; return(this.ResultExpression); }