public void ResolveUnaryExpression(UnaryExpression node) { if (node.NodeType == ExpressionType.Not && node.Operand.NodeType == ExpressionType.MemberAccess) { var rootType = ((MemberExpression)node.Operand).RootExpressionType(out var parameterStack); if (rootType == ExpressionType.Parameter) { if (parameterStack.Count == 2) { // 调用了导航属性 var propertyName = parameterStack.Pop(); var propertyFieldName = parameterStack.Pop(); JoinPropertyList.Add(propertyName); var prop = _master.Properties.Single(p => p.Name == propertyName); var propertyEntity = MyEntityContainer.Get(prop.PropertyInfo.PropertyType); var propertyProperty = propertyEntity.Properties.Single(p => p.Name == propertyFieldName); _stringStack.Push($"[{propertyName}].[{propertyProperty.FieldName}]=0"); } else if (parameterStack.Count == 1) { var propertyName = parameterStack.Pop(); var propInfo = _master.Properties.Single(p => p.Name == propertyName); _stringStack.Push($"[{_master.TableName}].[{propInfo.FieldName}]=0"); } else { throw new ArgumentException("尚未支持大于2层属性调用。如 student.Clazz.School.Id>10,请使用类似 student.Clazz.SchoolId > 0 替代"); } } else { var obj = ResolveValue(node.GetValue()); var parameterName = $"{_prefix}__p_{_parameterIndex++}"; _parameters.Add(new KeyValuePair <string, object>(parameterName, obj)); _stringStack.Push($" {parameterName} "); } } }
protected override Expression VisitUnary(UnaryExpression node) { if (node.NodeType == ExpressionType.Not && node.Operand.NodeType == ExpressionType.MemberAccess) { var rootType = ((MemberExpression)node.Operand).RootExpressionType(out var parameterStack); if (rootType == ExpressionType.Parameter) { ResolveStackToField(parameterStack); } else { var obj = ResolveValue(node.GetValue()); var parameterName = $"{_prefix}__p_{_parameterIndex++}"; _parameters.Add(new KeyValuePair <string, object>(parameterName, obj)); _stringStack.Push($" {parameterName} "); } } return(node); }
private string ResolveNotClause(UnaryExpression node) { var obj = node.Operand; if (obj.NodeType == ExpressionType.MemberAccess) { var expression = (MemberExpression)obj; var rootNodeType = expression.GetRootType(out var stack); if (rootNodeType == ExpressionType.Parameter) { var fieldName = ResolveStackToField(stack); return($"{fieldName}=1"); } } var value = (bool)node.GetValue(); return(value ? "1=1" : "1<>1"); }
/// <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)); } }
/// <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 Expression expression, JsonSerializerSettings jsonSerializerSettings) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } switch (expression.NodeType) { case ExpressionType.Constant: { ConstantExpression constantExpression = expression as ConstantExpression; if (constantExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(ConstantExpression)}\r\n\t{expression}", nameof(expression)); } return(constantExpression.GetValue()); } 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)); } return(methodCallExpression.GetValue(jsonSerializerSettings)); } case ExpressionType.Convert: { 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(unaryExpression.GetValue(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(memberExpression.GetValue(jsonSerializerSettings)); } case ExpressionType.New: { NewExpression newExpression = expression as NewExpression; if (newExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(NewExpression)}\r\n\t{expression}", nameof(expression)); } return(newExpression.GetValue(jsonSerializerSettings)); } 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)); } object unaryValue = unaryExpression.GetValue(jsonSerializerSettings); if (unaryValue == null || (unaryValue.GetType() != typeof(bool) && unaryValue.GetType() != typeof(bool?))) { throw new ArgumentException($"Invalid type", nameof(expression)); } return(!((bool)unaryValue)); } case ExpressionType.Parameter: { ParameterExpression parameterExpression = expression as ParameterExpression; if (parameterExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(ParameterExpression)}\r\n\t{expression}", nameof(expression)); } throw new ArgumentException($"Invalid expression type {expression.NodeType}\r\n\t{expression}", nameof(expression)); } case ExpressionType.NewArrayInit: { NewArrayExpression newArrayExpression = expression as NewArrayExpression; if (newArrayExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(NewArrayExpression)}\r\n\t{expression}", nameof(expression)); } return(newArrayExpression.Expressions.Select(_ => _.GetValue(jsonSerializerSettings)).ToArray()); } default: throw new ArgumentException($"Invalid expression type {expression.NodeType}\r\n\t{expression}", nameof(expression)); } }
public static object GetValue(this Expression expression) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } switch (expression.NodeType) { case ExpressionType.Constant: { ConstantExpression constantExpression = expression as ConstantExpression; if (constantExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(ConstantExpression)}\r\n\t{expression}", nameof(expression)); } return(constantExpression.GetValue()); } 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)); } return(methodCallExpression.GetValue()); } case ExpressionType.Convert: { 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(unaryExpression.GetValue()); } 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(memberExpression.GetValue()); } case ExpressionType.New: { NewExpression newExpression = expression as NewExpression; if (newExpression == null) { throw new ArgumentException($"Expected {nameof(expression)} to be of type {nameof(NewExpression)}\r\n\t{expression}", nameof(expression)); } return(newExpression.GetValue()); } default: throw new ArgumentException($"Invalid expression type {expression.NodeType}\r\n\t{expression}", nameof(expression)); } }