/// <summary> /// Builds the query dictionary . /// </summary> /// <returns>The query.</returns> /// <param name="model">Model.</param> /// <typeparam name="TModel">The 1st type parameter.</typeparam> public static IEnumerable <KeyValuePair <String, Object> > BuildQuery <TModel>(Expression <Func <TModel, bool> > model, bool stripNullChecks = false) { List <KeyValuePair <String, Object> > retVal = new List <KeyValuePair <string, Object> >(); var visitor = new HttpQueryExpressionVisitor(retVal); visitor.Visit(model); if (stripNullChecks) { retVal.RemoveAll(o => retVal.Any(c => c.Key == o.Key && c.Value != o.Value) && o.Value.Equals("!null")); } return(retVal); }
/// <summary> /// Visit method call /// </summary> protected override Expression VisitMethodCall(MethodCallExpression node) { switch (node.Method.Name) { case "Contains": { var parmName = this.ExtractPath(node.Object, false); object parmValue = this.ExtractValue(node.Arguments[0]); this.AddCondition(parmName, "~" + parmValue.ToString()); return(null); } case "StartsWith": { var parmName = this.ExtractPath(node.Object, false); object parmValue = this.ExtractValue(node.Arguments[0]); this.AddCondition(parmName, "^" + parmValue.ToString()); return(null); } case "Any": { var parmName = this.ExtractPath(node.Arguments[0], false); // Process lambda var result = new List <KeyValuePair <string, object> >(); var subQueryExpressionVisitor = new HttpQueryExpressionVisitor(result); if (node.Arguments.Count == 2) { subQueryExpressionVisitor.Visit(node.Arguments[1]); // Result foreach (var itm in result) { this.AddCondition(String.Format("{0}.{1}", parmName, itm.Key), itm.Value); } return(null); } else { return(null); } } default: return(base.VisitMethodCall(node)); } }
/// <summary> /// Builds the query dictionary . /// </summary> /// <returns>The query.</returns> /// <param name="model">Model.</param> public static String BuildPropertySelector(LambdaExpression model) { var visitor = new HttpQueryExpressionVisitor(new List <KeyValuePair <string, object> >(), model.Parameters[0].Type); return(visitor.ExtractPropertySelector(model)); }
/// <summary> /// Visit method call optionally negating any values parsed /// </summary> private Expression VisitMethodCall(MethodCallExpression node, bool negate) { switch (node.Method.Name) { case "Contains": { if (node.Object == null && node.Method.DeclaringType == typeof(Enumerable)) { return(this.ParseArrayContains(node, negate)); } else { var parmName = this.ExtractPath(node.Object, false); object parmValue = this.ExtractValue(node.Arguments[0]); this.AddCondition(parmName, (negate ? "!" : "~") + parmValue.ToString()); return(null); } } case "StartsWith": { var parmName = this.ExtractPath(node.Object, false); object parmValue = this.ExtractValue(node.Arguments[0]); this.AddCondition(parmName, (negate ? "!" : "^") + parmValue.ToString()); return(null); } case "Any": { var parmName = this.ExtractPath(node.Arguments[0], false); // Process lambda var result = new List <KeyValuePair <string, object> >(); var subQueryExpressionVisitor = new HttpQueryExpressionVisitor(result, node.Arguments[0].Type); if (node.Arguments.Count == 2) { subQueryExpressionVisitor.Visit(node.Arguments[1]); // Result foreach (var itm in result) { this.AddCondition(String.Format("{0}.{1}", parmName, itm.Key), negate ? $"!{itm.Value}" : itm.Value); } return(null); } else { return(null); } } default: // extended fn? { var extendedFn = QueryFilterExtensions.GetExtendedFilterByMethod(node.Method); if (extendedFn == null) { throw new MissingMemberException($"Cannot find extension method {node.Method}"); } if (extendedFn.ExtensionMethod.ReturnType == typeof(bool)) { var parmName = this.ExtractPath(node.Arguments[0], false); if (parmName == null && typeof(IdentifiedData).IsAssignableFrom(node.Arguments[0].Type)) { parmName = "id"; } else if (parmName == null) { throw new InvalidOperationException($"Cannot determine how to map {extendedFn.Name}"); } var callValue = $"{(negate ? "!" : "")}:({extendedFn.Name}"; if (node.Arguments.Count > 1) { callValue += $"|{String.Join(",", node.Arguments.Skip(1).Select(o => this.PrepareValue(this.ExtractValue(o), true)))}"; } callValue += ")"; this.AddCondition(parmName, callValue); return(node); } return(null); } } }