private Expression ApplyFilters(Expression node) { var nodeElementType = node.Type.GetElementTypeIfCollection(); if (_expressions.Keys.Any(x => x == _pathSoFar + node.ToString().Replace(ProjectToParameterName, string.Empty))) { var exp = _expressions[_pathSoFar + node.ToString().Replace(ProjectToParameterName, string.Empty)] as LambdaExpression; Expression newExp = null; //See if there's an applicable root filter to combine with the .With expression var parameterType = exp.Parameters[0].Type.GetElementTypeIfCollection(); if (_rootFilters != null && _rootFilters.ContainsKey(parameterType)) { //Combine the 2 filtering expressions var lamb = _rootFilters[parameterType] as LambdaExpression; newExp = ParameterReplacer.Replace(exp.Body, exp.Parameters.First(), lamb.Body); MethodCallExpression arg = null; if ((newExp as MethodCallExpression).Arguments[0].NodeType == ExpressionType.Call) { arg = ((newExp as MethodCallExpression).Arguments[0] as MethodCallExpression); } else { arg = ((newExp as MethodCallExpression).Arguments[0] as UnaryExpression).Operand as MethodCallExpression; } Expression param = arg; while (param.NodeType != ExpressionType.Parameter) { param = (param as MethodCallExpression).Arguments[0]; } //combine the new expression with the existing member access expression newExp = ParameterReplacer.Replace(newExp, param as ParameterExpression, node); } else //no root filter, just use the .With expression { //combine the single filtering expression with the existing member access expression newExp = ParameterReplacer.Replace(exp.Body, exp.Parameters.First(), node); } return(newExp); } else if (_rootFilters != null && _rootFilters.ContainsKey(nodeElementType))//see if there's an applicable root filter to use { var lamb = _rootFilters[nodeElementType] as LambdaExpression; //combine the single filtering expression with the existing member access expression var newExp = ParameterReplacer.Replace(lamb.Body, lamb.Parameters.First(), node); return(newExp); } else //nothing to apply, just continue { return(node); } }
protected override Expression VisitConstant(ConstantExpression node) { if (node.Type.IsGenericType && node.Type.GetGenericTypeDefinition() == typeof(ObjectQuery <>)) { //this is the root node. Need to transform any applicable root filter and apply it. var elementType = node.Type.GetElementTypeIfCollection(); if (_rootFilters.ContainsKey(elementType)) { var lamb = _rootFilters[elementType] as LambdaExpression; var casted = Expression.Convert(lamb.Body, typeof(ObjectQuery <>).MakeGenericType(elementType)); //combine the single filtering expression with the existing member access expression var composed = ParameterReplacer.Replace(casted, lamb.Parameters.First(), node); return(composed); } } return(base.VisitConstant(node)); }