protected override Expression VisitExtension(Expression extensionExpression) { if (extensionExpression is NavigationBindingExpression navigationBindingExpression) { var result = navigationBindingExpression.RootParameter.BuildPropertyAccess(navigationBindingExpression.NavigationTreeNode.ToMapping); return(result); } if (extensionExpression is NavigationExpansionRootExpression navigationExpansionRootExpression) { return(Visit(navigationExpansionRootExpression.Unwrap())); } if (extensionExpression is NavigationExpansionExpression navigationExpansionExpression) { var includeResult = ApplyIncludes(navigationExpansionExpression); var state = includeResult.state; var result = Visit(includeResult.operand); if (!state.ApplyPendingSelector && state.PendingOrderings.Count == 0 && state.PendingTags.Count == 0 && state.PendingCardinalityReducingOperator == null && state.MaterializeCollectionNavigation == null) { return(result); } var parameter = Expression.Parameter(result.Type.GetSequenceType()); foreach (var pendingOrdering in state.PendingOrderings) { var remappedKeySelectorBody = new ExpressionReplacingVisitor(pendingOrdering.keySelector.Parameters[0], state.CurrentParameter).Visit(pendingOrdering.keySelector.Body); var newSelectorBody = new NavigationPropertyUnbindingVisitor(state.CurrentParameter).Visit(remappedKeySelectorBody); var newSelector = Expression.Lambda(newSelectorBody, state.CurrentParameter); var orderingMethod = pendingOrdering.method.MakeGenericMethod(state.CurrentParameter.Type, newSelectorBody.Type); result = Expression.Call(orderingMethod, result, newSelector); } if (state.ApplyPendingSelector) { var pendingSelector = (LambdaExpression) new NavigationPropertyUnbindingVisitor(state.CurrentParameter).Visit(state.PendingSelector); var pendingSelectorBodyType = pendingSelector.Type.GetGenericArguments()[1]; var pendingSelectMathod = result.Type.IsGenericType && (result.Type.GetGenericTypeDefinition() == typeof(IEnumerable <>) || result.Type.GetGenericTypeDefinition() == typeof(IOrderedEnumerable <>)) ? LinqMethodHelpers.EnumerableSelectMethodInfo.MakeGenericMethod(parameter.Type, pendingSelectorBodyType) : LinqMethodHelpers.QueryableSelectMethodInfo.MakeGenericMethod(parameter.Type, pendingSelectorBodyType); result = Expression.Call(pendingSelectMathod, result, pendingSelector); parameter = Expression.Parameter(result.Type.GetSequenceType()); } if (state.PendingTags.Count > 0) { var withTagMethodInfo = EntityFrameworkQueryableExtensions.TagWithMethodInfo.MakeGenericMethod(parameter.Type); foreach (var pendingTag in state.PendingTags) { result = Expression.Call(withTagMethodInfo, result, Expression.Constant(pendingTag)); } } if (state.PendingCardinalityReducingOperator != null) { var terminatingOperatorMethodInfo = state.PendingCardinalityReducingOperator.MakeGenericMethod(parameter.Type); result = Expression.Call(terminatingOperatorMethodInfo, result); } if (state.MaterializeCollectionNavigation != null) { var entityType = state.MaterializeCollectionNavigation.ClrType.IsGenericType ? state.MaterializeCollectionNavigation.ClrType.GetGenericArguments()[0] : state.MaterializeCollectionNavigation.GetTargetType().ClrType; result = Expression.Call( NavigationExpansionHelpers.MaterializeCollectionNavigationMethodInfo.MakeGenericMethod( state.MaterializeCollectionNavigation.ClrType, entityType), result, Expression.Constant(state.MaterializeCollectionNavigation)); } if (navigationExpansionExpression.Type != result.Type && navigationExpansionExpression.Type.IsGenericType) { if (navigationExpansionExpression.Type.GetGenericTypeDefinition() == typeof(IOrderedQueryable <>)) { var toOrderedQueryableMethodInfo = ToOrderedQueryableMethod.MakeGenericMethod(parameter.Type); return(Expression.Call(toOrderedQueryableMethodInfo, result)); } else if (navigationExpansionExpression.Type.GetGenericTypeDefinition() == typeof(IOrderedEnumerable <>)) { var toOrderedEnumerableMethodInfo = ToOrderedEnumerableMethod.MakeGenericMethod(parameter.Type); return(Expression.Call(toOrderedEnumerableMethodInfo, result)); } } return(result); } return(base.VisitExtension(extensionExpression)); }
protected override Expression VisitExtension(Expression extensionExpression) { switch (extensionExpression) { case NavigationBindingExpression navigationBindingExpression: return(navigationBindingExpression.RootParameter.BuildPropertyAccess( navigationBindingExpression.NavigationTreeNode.ToMapping)); case NavigationExpansionRootExpression navigationExpansionRootExpression: return(Visit(navigationExpansionRootExpression.Unwrap())); case NavigationExpansionExpression navigationExpansionExpression: { var(result, state) = ApplyIncludes(navigationExpansionExpression); result = Visit(result); if (!state.ApplyPendingSelector && state.PendingOrderings.Count == 0 && state.PendingCardinalityReducingOperator == null && state.MaterializeCollectionNavigation == null) { return(result); } var parameterType = result.Type.GetSequenceType(); foreach (var pendingOrdering in state.PendingOrderings) { var remappedKeySelectorBody = new ExpressionReplacingVisitor(pendingOrdering.keySelector.Parameters[0], state.CurrentParameter).Visit(pendingOrdering.keySelector.Body); var newSelectorBody = new NavigationPropertyUnbindingVisitor(state.CurrentParameter).Visit(remappedKeySelectorBody); var newSelector = Expression.Lambda(newSelectorBody, state.CurrentParameter); var orderingMethod = pendingOrdering.method.MakeGenericMethod(state.CurrentParameter.Type, newSelectorBody.Type); result = Expression.Call(orderingMethod, result, newSelector); } if (state.ApplyPendingSelector) { var pendingSelector = (LambdaExpression) new NavigationPropertyUnbindingVisitor(state.CurrentParameter).Visit(state.PendingSelector); var pendingSelectorBodyType = pendingSelector.Type.GetGenericArguments()[1]; var pendingSelectMethod = result.Type.IsGenericType && (result.Type.GetGenericTypeDefinition() == typeof(IEnumerable <>) || result.Type.GetGenericTypeDefinition() == typeof(IOrderedEnumerable <>)) ? LinqMethodHelpers.EnumerableSelectMethodInfo.MakeGenericMethod(parameterType, pendingSelectorBodyType) : LinqMethodHelpers.QueryableSelectMethodInfo.MakeGenericMethod(parameterType, pendingSelectorBodyType); result = Expression.Call(pendingSelectMethod, result, pendingSelector); parameterType = result.Type.GetSequenceType(); } if (state.PendingCardinalityReducingOperator != null) { result = Expression.Call(state.PendingCardinalityReducingOperator, result); } if (state.MaterializeCollectionNavigation != null) { result = new MaterializeCollectionNavigationExpression(result, state.MaterializeCollectionNavigation); } if (navigationExpansionExpression.Type != result.Type && navigationExpansionExpression.Type.IsGenericType) { if (navigationExpansionExpression.Type.GetGenericTypeDefinition() == typeof(IOrderedQueryable <>)) { var toOrderedQueryableMethodInfo = ToOrderedQueryableMethod.MakeGenericMethod(parameterType); return(Expression.Call(toOrderedQueryableMethodInfo, result)); } if (navigationExpansionExpression.Type.GetGenericTypeDefinition() == typeof(IOrderedEnumerable <>)) { var toOrderedEnumerableMethodInfo = ToOrderedEnumerableMethod.MakeGenericMethod(parameterType); return(Expression.Call(toOrderedEnumerableMethodInfo, result)); } } return(result); } } return(base.VisitExtension(extensionExpression)); }