public Expression <Func <T, bool> > AsExpression <T>() where T : class { QueryCollection queryCollection = new QueryCollection(); var properties = typeof(T).GetTypeInfo().GetProperties(); if (Columns == null) { return(t => true); } foreach (var item in Columns) { var p = properties.FirstOrDefault(m => m.Name.Equals(item.Name, StringComparison.OrdinalIgnoreCase)); if (p == null) { continue; } var realType = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType; string value = null; if (item.Search != null && item.Search.Value.IsNotNullAndWhiteSpace()) { value = item.Search.Value; } else if (Search != null && Search.Value.IsNotNullAndWhiteSpace() && realType == typeof(string)) { value = Search.Value; } if ((item.Search.Opeartor == Query.Operators.Range && item.Search.ValueMin.IsNullOrWhiteSpace() && item.Search.ValueMax.IsNullOrWhiteSpace()) || (item.Search.Opeartor != Query.Operators.Range && value.IsNullOrWhiteSpace())) { continue; } Query query = new Query(); query.Name = p.Name; try { query.Value = ReflectorHelper.ValueConvert(p, value); query.ValueMin = ReflectorHelper.ValueConvert(p, item.Search.ValueMin); query.ValueMax = ReflectorHelper.ValueConvert(p, item.Search.ValueMax); //if (query.ValueMax != null && query.ValueMax is DateTime) //{ // query.ValueMax = ((DateTime)query.ValueMax).AddDays(1).AddMilliseconds(-1); //} } catch (Exception e) { continue; } query.Operator = item.Search.Opeartor; queryCollection.Add(query); } return(queryCollection.AsExpression <T>(Query.Condition.AndAlso)); }
public Expression <Func <T, bool> > AsExpression <T>(Query.Condition?condition = Query.Condition.OrElse) where T : class { Type targetType = typeof(T); TypeInfo typeInfo = targetType.GetTypeInfo(); var parameter = Expression.Parameter(targetType, ParameterSymbol); Expression expression = null; Func <Expression, Expression, Expression> Append = (exp1, exp2) => { if (exp1 == null) { return(exp2); } return((condition ?? Query.Condition.OrElse) == Query.Condition.OrElse ? Expression.OrElse(exp1, exp2) : Expression.AndAlso(exp1, exp2)); }; foreach (var item in this) { Expression property = GetPropertyExpression(parameter, item.Name); if (property == null || (item.Operator != Query.Operators.Range && item.Value == null) || (item.Operator == Query.Operators.Range && item.ValueMin == null && item.ValueMax == null)) { continue; } Type realType = Nullable.GetUnderlyingType(property.Type) ?? property.Type; if (item.Value != null) { if (realType.GetTypeInfo().IsEnum) { Type underlyingType = Enum.GetUnderlyingType(realType); item.Value = Convert.ChangeType(item.Value, underlyingType); property = Expression.Convert(property, underlyingType); } else if (item.Value.GetType().IsArray) { var objArray = item.Value as object[]; item.Value = ReflectorHelper.ValueConvert(realType, objArray); } else { item.Value = Convert.ChangeType(item.Value, realType); } } Expression <Func <object> > valueLamba = () => item.Value; switch (item.Operator) { case Query.Operators.Equal: { expression = Append(expression, Expression.Equal(property, Expression.Convert(valueLamba.Body, property.Type))); break; } case Query.Operators.GreaterThan: { expression = Append(expression, Expression.GreaterThan(property, Expression.Convert(valueLamba.Body, property.Type))); break; } case Query.Operators.GreaterThanOrEqual: { expression = Append(expression, Expression.GreaterThanOrEqual(property, Expression.Convert(valueLamba.Body, property.Type))); break; } case Query.Operators.LessThan: { expression = Append(expression, Expression.LessThan(property, Expression.Convert(valueLamba.Body, property.Type))); break; } case Query.Operators.LessThanOrEqual: { expression = Append(expression, Expression.LessThanOrEqual(property, Expression.Convert(valueLamba.Body, property.Type))); break; } case Query.Operators.Contains: { var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, property)); var contains = Expression.Call(property, "Contains", null, Expression.Convert(valueLamba.Body, property.Type)); expression = Append(expression, Expression.AndAlso(nullCheck, contains)); break; } case Query.Operators.In: //value必须是数组类型 { var constantExp = Expression.Constant(item.Value, item.Value.GetType()); Type typeIfNullable = Nullable.GetUnderlyingType(property.Type); if (typeIfNullable != null) { property = Expression.Call(property, "GetValueOrDefault", Type.EmptyTypes); } var contains = Expression.Call(typeof(Enumerable), "Contains", new Type[] { realType }, constantExp, property); //var contains = Expression.Call(constantExp, "Contains", null, property); expression = Append(expression, contains); break; } case Query.Operators.StartWith: { var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, property)); var startsWith = Expression.Call(property, "StartsWith", null, Expression.Convert(valueLamba.Body, property.Type)); expression = Append(expression, Expression.AndAlso(nullCheck, startsWith)); break; } case Query.Operators.EndWidth: { var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, property)); var endsWith = Expression.Call(property, "EndsWith", null, Expression.Convert(valueLamba.Body, property.Type)); expression = Append(expression, Expression.AndAlso(nullCheck, endsWith)); break; } case Query.Operators.Range: { Expression minExp = null, maxExp = null; if (item.ValueMin != null) { var minValue = Convert.ChangeType(item.ValueMin, realType); Expression <Func <object> > minValueLamda = () => minValue; minExp = Expression.GreaterThanOrEqual(property, Expression.Convert(minValueLamda.Body, property.Type)); } if (item.ValueMax != null) { var maxValue = Convert.ChangeType(item.ValueMax, realType); Expression <Func <object> > maxValueLamda = () => maxValue; maxExp = Expression.LessThanOrEqual(property, Expression.Convert(maxValueLamda.Body, property.Type)); } if (minExp != null && maxExp != null) { expression = Append(expression, Expression.AndAlso(minExp, maxExp)); } else if (minExp != null) { expression = Append(expression, minExp); } else if (maxExp != null) { expression = Append(expression, maxExp); } break; } } } if (expression == null) { return(null); } return((Expression <Func <T, bool> >)Expression.Lambda(expression, parameter)); }
public LambdaExpression GetExpression(Dictionary <string, object> enviromens = null) { FilterValues = FilterValue?.Split(','); if (enviromens != null && enviromens.ContainsKey(FilterValue)) { var realValue = enviromens[FilterValue]; var realValueType = realValue.GetType(); if (realValueType.GetInterface(nameof(IEnumerable)) != null && typeof(string) != realValueType) { realValueType = realValueType.GetGenericArguments()[0]; MethodInfo toArrayMethod = typeof(Enumerable).GetMethod("ToArray") .MakeGenericMethod(new System.Type[] { realValueType }); FilterValues = toArrayMethod.Invoke(null, new object[] { realValue }) as object[]; } else { FilterValues = new object[] { realValue } }; if (Type.GetType(this.PropertyType) != realValueType) { throw new NotSupportedException("the propertyType can not compare to the value type "); } } PropertyPath = string.Join(".", PropertyNames); var enityType = Type.GetType(EntityType); LambdaExpression lambdaExpression = null; var parameter = Expression.Parameter(enityType, QueryCollection.ParameterSymbol); switch (FieldKind) { case FieldKind.ValueType: //如:m.Id==2 或者m.Name.Contains("a") 或者m.Group.Name="a" case FieldKind.Reference: //reference下的属性处理与ValueType是一致的,其实可以忽略掉 { var queryCollection = new QueryCollection(); var query = new Query { Name = this.PropertyPath, Operator = this.Operator }; switch (query.Operator) { case Operators.Range: { query.ValueMin = this.FilterValues[0]; query.ValueMax = this.FilterValues[1]; break; } case Operators.In: { query.Value = this.FilterValues; break; } default: query.Value = this.FilterValues[0]; break; } queryCollection.Add(query); var method = typeof(QueryCollection).GetMethod("AsExpression"); method = method.MakeGenericMethod(enityType); lambdaExpression = (LambdaExpression)method.GetReflector().Invoke(queryCollection, Query.Condition.AndAlso); break; } case FieldKind.ICollection: { if (this.RuleGroup == null) { break; } var childLambda = this.RuleGroup.GetExpression(); var member = QueryCollection.GetPropertyExpression(parameter, PropertyPath); if (member.Type.GetInterface(nameof(IEnumerable)) != null) { lambdaExpression = Expression.Lambda( Expression.Call(typeof(Enumerable), "Any", new Type[] { Type.GetType(this.RuleGroup.EntityType) }, member, childLambda), parameter); } break; } case FieldKind.EnvType: //用户的上下文环境变量,在json字符串阶段需提前用变量值替换掉,替换后,propertyPath其实就是一个值 { var propertyType = Type.GetType(this.PropertyType); if (enviromens == null) { throw new ArgumentNullException("enviroment values is null"); } if (!enviromens.ContainsKey(this.PropertyPath)) { throw new ArgumentNullException("not such enviroment key and value"); } var environmentValue = enviromens[this.PropertyPath]; var left = Expression.Constant(environmentValue); Expression expression = null; switch (Operator) { case Query.Operators.Equal: { var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0])); expression = Expression.Equal(left, right); break; } case Query.Operators.GreaterThan: { var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0])); expression = Expression.GreaterThan(left, right); break; } case Query.Operators.GreaterThanOrEqual: { var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0])); expression = Expression.GreaterThanOrEqual(left, right); break; } case Query.Operators.LessThan: { var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0])); expression = Expression.LessThan(left, right); break; } case Query.Operators.LessThanOrEqual: { var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0])); expression = Expression.LessThanOrEqual(left, right); break; } case Query.Operators.Contains: { var itemType = propertyType != typeof(string) && propertyType.GetInterface(nameof(IEnumerable)) != null ? propertyType.GenericTypeArguments[0] : propertyType; var right = Expression.Constant(ReflectorHelper.ValueConvert(itemType, FilterValues[0])); expression = Expression.Call(left, "Contains", null, right); break; } case Query.Operators.In: //value必须是集合类型 { var constantVaule = ReflectorHelper.ValueConvert(propertyType, FilterValues); var right = Expression.Constant(constantVaule); expression = Expression.Call(typeof(Enumerable), "Contains", new Type[] { propertyType }, right, left); break; } case Query.Operators.StartWith: { var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0])); expression = Expression.Call(left, "StartsWith", null, right); break; } case Query.Operators.EndWidth: { var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0])); expression = Expression.Call(left, "EndsWith", null, right); break; } case Query.Operators.Range: { Expression minExp = null, maxExp = null; if (FilterValues.Length > 0 && FilterValues[0] != null) { var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0])); minExp = Expression.GreaterThanOrEqual(left, right); } if (FilterValues.Length > 1 && FilterValues[1] != null) { var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[1])); maxExp = Expression.LessThanOrEqual(left, right); } if (minExp != null && maxExp != null) { expression = Expression.AndAlso(minExp, maxExp); } else if (minExp != null) { expression = minExp; } else if (maxExp != null) { expression = maxExp; } break; } } lambdaExpression = Expression.Lambda(expression, parameter); break; } default: break; } return(lambdaExpression); } }