/// <summary> /// Get the value from an expression. /// </summary> /// <param name="expression">The expression to be evaluated.</param> /// <returns>the value.</returns> public static object GetValue(this MethodCallExpression expression, JsonSerializerSettings jsonSerializerSettings) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (expression.Method.DeclaringType == typeof(SearchFns)) { switch (expression.Method.Name) { case nameof(SearchFns.IsMatch): { string search = expression.Arguments[0].GetValue(jsonSerializerSettings) as string; NewArrayExpression searchFieldsNewArrayExpression = expression.Arguments[1] as NewArrayExpression; IEnumerable <string> searchFields = searchFieldsNewArrayExpression.Expressions.Select(_ => PropertyNameUtility.GetPropertyName(_, jsonSerializerSettings, false).ToString()).ToArray(); return($"search.ismatch('{search}', '{string.Join(", ", searchFields)}')"); } case nameof(SearchFns.IsMatchScoring): { string search = expression.Arguments[0].GetValue(jsonSerializerSettings) as string; NewArrayExpression searchFieldsNewArrayExpression = expression.Arguments[1] as NewArrayExpression; IEnumerable <string> searchFields = searchFieldsNewArrayExpression.Expressions.Select(_ => PropertyNameUtility.GetPropertyName(_, jsonSerializerSettings, false).ToString()).ToArray(); return($"search.ismatchscoring('{search}', '{string.Join(", ", searchFields)}')"); } case nameof(SearchFns.In): { string variable = PropertyNameUtility.GetPropertyName(expression.Arguments[0], jsonSerializerSettings, false); NewArrayExpression valueListNewArrayExpression = expression.Arguments[1] as NewArrayExpression; IEnumerable <object> valueList = valueListNewArrayExpression.Expressions.Select(_ => _.GetValue(jsonSerializerSettings)).ToArray(); return($"search.in('{variable}', '{string.Join(", ", valueList.Select(_ => _.ToString()).ToArray())}')"); } case nameof(SearchFns.Score): return("search.score()"); default: throw new ArgumentException($"Invalid method {expression.Method}\r\n\t{expression}", nameof(expression)); } } else { return(expression.Method.Invoke( expression.Object.GetValue(jsonSerializerSettings), expression.Arguments.Select(_ => _.GetValue(jsonSerializerSettings)).ToArray())); } }
/// <summary> /// Get the OData filter expression. /// </summary> /// <param name="unaryExpression">The expression from which to parse the OData filter.</param> /// <returns>the OData filter.</returns> public static string GetFilterExpression(UnaryExpression unaryExpression) { if (unaryExpression == null) { throw new ArgumentNullException(nameof(unaryExpression)); } string operand = null; switch (unaryExpression.Operand.NodeType) { case ExpressionType.MemberAccess: { MemberExpression memberExpression = unaryExpression.Operand as MemberExpression; if (memberExpression == null) { throw new ArgumentException($"Expected {nameof(unaryExpression)}.{nameof(UnaryExpression.Operand)} to be of type {nameof(MemberExpression)}\r\n\t{unaryExpression}", nameof(unaryExpression)); } operand = PropertyNameUtility.GetPropertyName(memberExpression, false); } break; default: throw new ArgumentException($"Invalid expression type {unaryExpression.Operand.NodeType}\r\n\t{unaryExpression}", nameof(unaryExpression)); } switch (unaryExpression.NodeType) { case ExpressionType.IsFalse: case ExpressionType.Not: return($"not {operand}"); case ExpressionType.IsTrue: return($"{operand}"); default: throw new ArgumentException($"Invalid expression type {unaryExpression.NodeType}\r\n\t{unaryExpression}", nameof(unaryExpression)); } }
/// <summary> /// Get the OData filter expression. /// </summary> /// <param name="expression">The expression from which to parse the OData filter.</param> /// <returns>the OData filter.</returns> public static string GetFilterExpression(Expression expression) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } switch (expression.NodeType) { case ExpressionType.Equal: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.NotEqual: { BinaryExpression binaryExpression = expression as BinaryExpression; if (binaryExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(BinaryExpression)}\r\n\t{expression}", nameof(expression)); } return(GetFilterExpression(binaryExpression)); } case ExpressionType.IsFalse: case ExpressionType.IsTrue: case ExpressionType.Not: { UnaryExpression unaryExpression = expression as UnaryExpression; if (unaryExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(UnaryExpression)}\r\n\t{expression}", nameof(expression)); } return(GetFilterExpression(unaryExpression)); } case ExpressionType.MemberAccess: { MemberExpression memberExpression = expression as MemberExpression; if (memberExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(MemberExpression)}\r\n\t{expression}", nameof(expression)); } return(PropertyNameUtility.GetPropertyName(memberExpression, false)); } case ExpressionType.Call: { MethodCallExpression methodCallExpression = expression as MethodCallExpression; if (methodCallExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(MethodCallExpression)}\r\n\t{expression}", nameof(expression)); } switch (methodCallExpression.Method.Name) { case nameof(Queryable.Any): case nameof(Queryable.All): { IList <string> parts = new List <string>(); int idx = 0; foreach (Expression argumentExpression in methodCallExpression.Arguments) { idx++; switch (argumentExpression.NodeType) { case ExpressionType.MemberAccess: { MemberExpression argumentMemberExpression = argumentExpression as MemberExpression; if (argumentMemberExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(MemberExpression)}\r\n\t{methodCallExpression}", nameof(expression)); } parts.Add(PropertyNameUtility.GetPropertyName(argumentMemberExpression, false)); } break; case ExpressionType.Lambda: { LambdaExpression argumentLambdaExpression = argumentExpression as LambdaExpression; if (argumentLambdaExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(LambdaExpression)}\r\n\t{methodCallExpression}", nameof(expression)); } ParameterExpression argumentParameterExpression = argumentLambdaExpression.Parameters.SingleOrDefault() as ParameterExpression; if (argumentParameterExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}].{nameof(LambdaExpression.Parameters)}[0] to be of type {nameof(ParameterExpression)}\r\n\t{argumentLambdaExpression}", nameof(expression)); } string inner = GetFilterExpression(argumentLambdaExpression); parts.Add(Constants.ODataMemberAccessOperator); parts.Add(methodCallExpression.Method.Name.ToLowerInvariant()); parts.Add($"({argumentParameterExpression.Name}:{argumentParameterExpression.Name}"); if (string.IsNullOrWhiteSpace(inner) == false && inner.StartsWith(" ") == false) { parts.Add(Constants.ODataMemberAccessOperator); } parts.Add(inner); parts.Add(")"); } break; default: throw new ArgumentException($"Invalid expression type {argumentExpression.NodeType}\r\n\t{methodCallExpression}", nameof(expression)); } } return(string.Join(string.Empty, parts)); } case nameof(Queryable.Select): { IList <string> parts = new List <string>(); int idx = -1; foreach (Expression argumentExpression in methodCallExpression.Arguments) { idx++; switch (argumentExpression.NodeType) { case ExpressionType.MemberAccess: { MemberExpression argumentMemberExpression = argumentExpression as MemberExpression; if (argumentMemberExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(MemberExpression)}\r\n\t{expression}", nameof(expression)); } parts.Add(PropertyNameUtility.GetPropertyName(argumentMemberExpression, false)); } break; case ExpressionType.Lambda: { LambdaExpression argumentLambdaExpression = argumentExpression as LambdaExpression; if (argumentLambdaExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(LambdaExpression)}\r\n\t{expression}", nameof(expression)); } ParameterExpression argumentParameterExpression = argumentLambdaExpression.Parameters.SingleOrDefault() as ParameterExpression; if (argumentParameterExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}].{nameof(LambdaExpression.Parameters)}[0] to be of type {nameof(ParameterExpression)}\r\n\t{argumentLambdaExpression}", nameof(expression)); } string inner = GetFilterExpression(argumentLambdaExpression); parts.Add(Constants.ODataMemberAccessOperator); parts.Add(inner); } break; default: throw new ArgumentException($"Invalid expression type {argumentExpression.NodeType}\r\n\t{expression}", nameof(expression)); } } return(string.Join(string.Empty, parts)); } case nameof(string.Format): { Func <string> stringFormat = Expression.Lambda <Func <string> >(Expression.Convert(methodCallExpression, methodCallExpression.Type)).Compile(); return(stringFormat()); } default: throw new ArgumentException($"Invalid method {methodCallExpression.Method}\r\n\t{expression}", nameof(expression)); } } case ExpressionType.And: case ExpressionType.AndAlso: case ExpressionType.Or: case ExpressionType.OrElse: { BinaryExpression binaryExpression = expression as BinaryExpression; if (binaryExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(LambdaExpression.Body)} to be of type {nameof(BinaryExpression)}\r\n\t{expression}", nameof(expression)); } string op = expression.NodeType == ExpressionType.And || expression.NodeType == ExpressionType.AndAlso ? "and" : "or"; return($"({GetFilterExpression(binaryExpression.Left)}) {op} ({GetFilterExpression(binaryExpression.Right)})"); } default: throw new ArgumentException($"Invalid expression type {expression.NodeType}\r\n\t{expression}", nameof(expression)); } }
/// <summary> /// Get the OData filter expression. /// </summary> /// <param name="binaryExpression">The expression from which to parse the OData filter.</param> /// <returns>the OData filter.</returns> public static string GetFilterExpression(BinaryExpression binaryExpression) { if (binaryExpression == null || binaryExpression.Left == null || binaryExpression.Right == null) { throw new ArgumentNullException(nameof(binaryExpression)); } string op = null; switch (binaryExpression.NodeType) { case ExpressionType.Equal: op = "eq"; break; case ExpressionType.GreaterThan: op = "gt"; break; case ExpressionType.GreaterThanOrEqual: op = "ge"; break; case ExpressionType.LessThan: op = "lt"; break; case ExpressionType.LessThanOrEqual: op = "le"; break; case ExpressionType.NotEqual: op = "ne"; break; default: throw new ArgumentException($"Invalid expression type {binaryExpression.NodeType}\r\n\t{binaryExpression}", nameof(binaryExpression)); } string left = null; switch (binaryExpression.Left.NodeType) { case ExpressionType.MemberAccess: { MemberExpression memberExpression = binaryExpression.Left as MemberExpression; if (memberExpression == null) { throw new ArgumentException($"Expected {nameof(binaryExpression)}.{nameof(BinaryExpression.Left)} to be of type {nameof(MemberExpression)}\r\n\t{binaryExpression}", nameof(binaryExpression)); } left = PropertyNameUtility.GetPropertyName(memberExpression, false); } break; case ExpressionType.Parameter: left = string.Empty; break; case ExpressionType.Convert: { UnaryExpression unaryExpression = binaryExpression.Left as UnaryExpression; if (unaryExpression == null) { throw new ArgumentException($"Expected {nameof(binaryExpression)}.{nameof(BinaryExpression.Left)} to be of type {nameof(UnaryExpression)}\r\n\t{binaryExpression}", nameof(binaryExpression)); } switch (unaryExpression.Operand.NodeType) { case ExpressionType.MemberAccess: { MemberExpression memberExpression = unaryExpression.Operand as MemberExpression; if (unaryExpression == null) { throw new ArgumentException($"Expected {nameof(binaryExpression)}.{nameof(BinaryExpression.Left)}.{nameof(UnaryExpression.Operand)} to be of type {nameof(MemberExpression)}\r\n\t{binaryExpression}", nameof(binaryExpression)); } left = PropertyNameUtility.GetPropertyName(memberExpression, false); } break; default: throw new ArgumentException($"Invalid expression type {unaryExpression.Operand.GetType()}", nameof(binaryExpression)); } } break; default: throw new ArgumentException($"Invalid expression type {binaryExpression.Left.NodeType}\r\n\t{binaryExpression}", nameof(binaryExpression)); } object rightValue = binaryExpression.Right.GetValue(); if (rightValue == null) { throw new ArgumentException($"Invalid expression body type {binaryExpression.Right.GetType()}", nameof(binaryExpression)); } string right = null; if (rightValue.GetType() == typeof(string)) { right = string.Concat("'", rightValue as string, "'"); } else if (rightValue.GetType() == typeof(Guid) || rightValue.GetType() == typeof(Guid?) || rightValue.GetType() == typeof(TimeSpan) || rightValue.GetType() == typeof(TimeSpan?)) { right = string.Concat("'", rightValue.ToString().ToLowerInvariant(), "'"); } else if (rightValue.GetType() == typeof(DateTime) || rightValue.GetType() == typeof(DateTime?)) { right = string.Concat("'", ((DateTime)rightValue).ToString("O"), "'"); } else if (rightValue.GetType() == typeof(DateTimeOffset) || rightValue.GetType() == typeof(DateTimeOffset?)) { right = string.Concat("'", ((DateTimeOffset)rightValue).ToString("O"), "'"); } else if (rightValue.GetType() == typeof(bool) || rightValue.GetType() == typeof(bool?)) { right = rightValue.ToString().ToLowerInvariant(); } else { right = rightValue.ToString(); } return($"{left} {op} {right}"); }
/// <summary> /// Get the OData filter expression. /// </summary> /// <param name="expression">The expression from which to parse the OData filter.</param> /// <returns>the OData filter.</returns> public static string GetFilterExpression(Expression expression, JsonSerializerSettings jsonSerializerSettings) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } switch (expression.NodeType) { case ExpressionType.Equal: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.NotEqual: { BinaryExpression binaryExpression = expression as BinaryExpression; if (binaryExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(BinaryExpression)}\r\n\t{expression}", nameof(expression)); } return(GetFilterExpression(binaryExpression, jsonSerializerSettings)); } case ExpressionType.IsFalse: case ExpressionType.IsTrue: case ExpressionType.Not: { UnaryExpression unaryExpression = expression as UnaryExpression; if (unaryExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(UnaryExpression)}\r\n\t{expression}", nameof(expression)); } return(GetFilterExpression(unaryExpression, jsonSerializerSettings)); } case ExpressionType.MemberAccess: { MemberExpression memberExpression = expression as MemberExpression; if (memberExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(MemberExpression)}\r\n\t{expression}", nameof(expression)); } return(PropertyNameUtility.GetPropertyName(memberExpression, jsonSerializerSettings, false)); } case ExpressionType.Call: { MethodCallExpression methodCallExpression = expression as MethodCallExpression; if (methodCallExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(MethodCallExpression)}\r\n\t{expression}", nameof(expression)); } if (methodCallExpression.Method.DeclaringType == typeof(SearchFns)) { switch (methodCallExpression.Method.Name) { case nameof(SearchFns.IsMatch): { string search = methodCallExpression.Arguments[0].GetValue(jsonSerializerSettings) as string; NewArrayExpression searchFieldsNewArrayExpression = methodCallExpression.Arguments[1] as NewArrayExpression; IEnumerable <string> searchFields = searchFieldsNewArrayExpression.Expressions.Select(_ => PropertyNameUtility.GetPropertyName(_, jsonSerializerSettings, false).ToString()).ToArray(); return($"search.ismatch('{search}', '{string.Join(", ", searchFields)}')"); } case nameof(SearchFns.IsMatchScoring): { string search = methodCallExpression.Arguments[0].GetValue(jsonSerializerSettings) as string; NewArrayExpression searchFieldsNewArrayExpression = methodCallExpression.Arguments[1] as NewArrayExpression; IEnumerable <string> searchFields = searchFieldsNewArrayExpression.Expressions.Select(_ => PropertyNameUtility.GetPropertyName(_, jsonSerializerSettings, false).ToString()).ToArray(); return($"search.ismatchscoring('{search}', '{string.Join(", ", searchFields)}')"); } case nameof(SearchFns.In): { string variable = PropertyNameUtility.GetPropertyName(methodCallExpression.Arguments[0], jsonSerializerSettings, false); NewArrayExpression valueListNewArrayExpression = methodCallExpression.Arguments[1] as NewArrayExpression; IEnumerable <object> valueList = valueListNewArrayExpression.Expressions.Select(_ => _.GetValue(jsonSerializerSettings)).ToArray(); return($"search.in('{variable}', '{string.Join(", ", valueList.Select(_ => _.ToString()).ToArray())}')"); } case nameof(SearchFns.Score): return("search.score()"); default: throw new ArgumentException($"Invalid method {methodCallExpression.Method}\r\n\t{expression}", nameof(expression)); } } else { switch (methodCallExpression.Method.Name) { case nameof(Queryable.Any): case nameof(Queryable.All): { IList <string> parts = new List <string>(); int idx = 0; foreach (Expression argumentExpression in methodCallExpression.Arguments) { idx++; switch (argumentExpression.NodeType) { case ExpressionType.MemberAccess: { MemberExpression argumentMemberExpression = argumentExpression as MemberExpression; if (argumentMemberExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(MemberExpression)}\r\n\t{methodCallExpression}", nameof(expression)); } parts.Add(PropertyNameUtility.GetPropertyName(argumentMemberExpression, jsonSerializerSettings, false)); } break; case ExpressionType.Lambda: { LambdaExpression argumentLambdaExpression = argumentExpression as LambdaExpression; if (argumentLambdaExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(LambdaExpression)}\r\n\t{methodCallExpression}", nameof(expression)); } ParameterExpression argumentParameterExpression = argumentLambdaExpression.Parameters.SingleOrDefault() as ParameterExpression; if (argumentParameterExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}].{nameof(LambdaExpression.Parameters)}[0] to be of type {nameof(ParameterExpression)}\r\n\t{argumentLambdaExpression}", nameof(expression)); } string inner = GetFilterExpression(argumentLambdaExpression, jsonSerializerSettings); parts.Add(Constants.ODataMemberAccessOperator); parts.Add(methodCallExpression.Method.Name.ToLowerInvariant()); parts.Add($"({argumentParameterExpression.Name}:{argumentParameterExpression.Name}"); if (string.IsNullOrWhiteSpace(inner) == false && inner.StartsWith(" ") == false) { parts.Add(Constants.ODataMemberAccessOperator); } parts.Add(inner); parts.Add(")"); } break; default: throw new ArgumentException($"Invalid expression type {argumentExpression.NodeType}\r\n\t{methodCallExpression}", nameof(expression)); } } return(string.Join(string.Empty, parts)); } case nameof(Queryable.Select): { IList <string> parts = new List <string>(); int idx = -1; foreach (Expression argumentExpression in methodCallExpression.Arguments) { idx++; switch (argumentExpression.NodeType) { case ExpressionType.MemberAccess: { MemberExpression argumentMemberExpression = argumentExpression as MemberExpression; if (argumentMemberExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(MemberExpression)}\r\n\t{expression}", nameof(expression)); } parts.Add(PropertyNameUtility.GetPropertyName(argumentMemberExpression, jsonSerializerSettings, false)); } break; case ExpressionType.Lambda: { LambdaExpression argumentLambdaExpression = argumentExpression as LambdaExpression; if (argumentLambdaExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(LambdaExpression)}\r\n\t{expression}", nameof(expression)); } ParameterExpression argumentParameterExpression = argumentLambdaExpression.Parameters.SingleOrDefault() as ParameterExpression; if (argumentParameterExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}].{nameof(LambdaExpression.Parameters)}[0] to be of type {nameof(ParameterExpression)}\r\n\t{argumentLambdaExpression}", nameof(expression)); } string inner = GetFilterExpression(argumentLambdaExpression, jsonSerializerSettings); parts.Add(Constants.ODataMemberAccessOperator); parts.Add(inner); } break; default: throw new ArgumentException($"Invalid expression type {argumentExpression.NodeType}\r\n\t{expression}", nameof(expression)); } } return(string.Join(string.Empty, parts)); } case nameof(string.Format): { string format = null; IList <object> parts = new List <object>(); int idx = -1; foreach (Expression argumentExpression in methodCallExpression.Arguments) { idx++; switch (argumentExpression.NodeType) { case ExpressionType.Convert: { UnaryExpression unaryExpression = argumentExpression as UnaryExpression; if (unaryExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(UnaryExpression)}\r\n\t{expression}", nameof(expression)); } if (idx == 0) { format = unaryExpression.GetValue(jsonSerializerSettings)?.ToString(); } else { parts.Add(unaryExpression.GetValue(jsonSerializerSettings)); } } break; case ExpressionType.Constant: { ConstantExpression constantExpression = argumentExpression as ConstantExpression; if (constantExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(ConstantExpression)}\r\n\t{expression}", nameof(expression)); } if (idx == 0) { format = constantExpression.Value?.ToString(); } else { parts.Add(constantExpression.Value); } } break; case ExpressionType.MemberAccess: { MemberExpression argumentMemberExpression = argumentExpression as MemberExpression; if (argumentMemberExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(MemberExpression)}\r\n\t{expression}", nameof(expression)); } if (idx == 0) { format = PropertyNameUtility.GetPropertyName(argumentMemberExpression, jsonSerializerSettings, false); } else { parts.Add(PropertyNameUtility.GetPropertyName(argumentMemberExpression, jsonSerializerSettings, false)); } } break; case ExpressionType.Lambda: { LambdaExpression argumentLambdaExpression = argumentExpression as LambdaExpression; if (argumentLambdaExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}] to be of type {nameof(LambdaExpression)}\r\n\t{expression}", nameof(expression)); } ParameterExpression argumentParameterExpression = argumentLambdaExpression.Parameters.SingleOrDefault() as ParameterExpression; if (argumentParameterExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(methodCallExpression.Arguments)}[{idx}].{nameof(LambdaExpression.Parameters)}[0] to be of type {nameof(ParameterExpression)}\r\n\t{argumentLambdaExpression}", nameof(expression)); } string inner = GetFilterExpression(argumentLambdaExpression, jsonSerializerSettings); if (idx == 0) { format = inner; } else { parts.Add(inner); } } break; default: throw new ArgumentException($"Invalid expression type {argumentExpression.NodeType}\r\n\t{expression}", nameof(expression)); } } return(string.Format(format, parts.ToArray())); } default: throw new ArgumentException($"Invalid method {methodCallExpression.Method}\r\n\t{expression}", nameof(expression)); } } } case ExpressionType.And: case ExpressionType.AndAlso: case ExpressionType.Or: case ExpressionType.OrElse: { BinaryExpression binaryExpression = expression as BinaryExpression; if (binaryExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(LambdaExpression.Body)} to be of type {nameof(BinaryExpression)}\r\n\t{expression}", nameof(expression)); } string op = expression.NodeType == ExpressionType.And || expression.NodeType == ExpressionType.AndAlso ? "and" : "or"; return($"({GetFilterExpression(binaryExpression.Left, jsonSerializerSettings)}) {op} ({GetFilterExpression(binaryExpression.Right, jsonSerializerSettings)})"); } case ExpressionType.Constant: { ConstantExpression constantExpression = expression as ConstantExpression; if (constantExpression == null) { throw new ArgumentException($"Expected {nameof(expression)}.{nameof(LambdaExpression.Body)} to be of type {nameof(ConstantExpression)}\r\n\t{expression}", nameof(expression)); } return(constantExpression.Value?.ToString()); } default: throw new ArgumentException($"Invalid expression type {expression.NodeType}\r\n\t{expression}", nameof(expression)); } }