private static Expression BuildMatchExpression(Expression targetProperty, string propertyValue, StringMatchMethod matchMethod, ParameterExpression target) { if (targetProperty == null) { return(null); } if (String.IsNullOrEmpty(propertyValue)) { return(null); } Expression noMatch = Expression.Constant(false); var propertyExp = ExpressionHelper.ExtractPropertyChain(targetProperty, target); if (IsIntegral(propertyExp.Type)) { int val; if (!int.TryParse(propertyValue, out val)) { return(noMatch); } return(Expression.Equal(propertyExp, Expression.Constant(val))); } if (IsBoolean(propertyExp.Type)) { bool val; if (!bool.TryParse(propertyValue, out val)) { return(noMatch); } return(Expression.Equal(propertyExp, Expression.Constant(val))); } if (IsEnum(propertyExp.Type)) { var val = Enum.Parse(propertyExp.Type, propertyValue); if (val == null) { return(noMatch); } var valExp = Expression.Constant(val, propertyExp.Type); return(Expression.Equal(Expression.Convert(propertyExp, Enum.GetUnderlyingType(propertyExp.Type)), Expression.Convert(valExp, Enum.GetUnderlyingType(propertyExp.Type)))); } if (IsDateTime(propertyExp.Type)) { var range = propertyValue.Split('-'); if (range == null) { return(noMatch); } var propertyExpAsNullable = Expression.Convert(propertyExp, typeof(Nullable <>).MakeGenericType(propertyExp.Type)); if (range.Length > 1) { DateTime dateFrom, dateTill; if (!DateTime.TryParse(range[0], CultureInfo.InvariantCulture, DateTimeStyles.None, out dateFrom)) { return(noMatch); } if (!DateTime.TryParse(range[1], CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTill)) { return(noMatch); } dateTill = dateTill.AddDays(1); var propertyGreatherThan = Expression.GreaterThanOrEqual(propertyExpAsNullable, Expression.Constant(dateFrom, typeof(DateTime?))); var propertyLessThan = Expression.LessThan(propertyExpAsNullable, Expression.Constant(dateTill, typeof(DateTime?))); return(Expression.AndAlso(propertyGreatherThan, propertyLessThan)); } else { DateTime date; if (!DateTime.TryParse(propertyValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out date)) { return(noMatch); } //if needed, it is possible to match by date part only, utilizing the DbFunctions.TruncateTime method (EF6). //MethodInfo methodInfo = typeof(DbFunctions).GetMethod("TruncateTime", new Type[] { propertyExpAsNullable.Type }); //return Expression.Equal(Expression.Call(methodInfo, propertyExpAsNullable), Expression.Constant(date, typeof(DateTime?))); return(Expression.Equal(propertyExpAsNullable, Expression.Constant(date, typeof(DateTime?)))); } } var propertyExpAsString = Expression.Call(Expression.Convert(propertyExp, typeof(object)), typeof(object).GetMethod("ToString")); var propertyContainsExpr = Expression.Call(propertyExpAsString, typeof(string).GetMethod(matchMethod.ToString(), new[] { typeof(string) }), Expression.Constant(propertyValue)); //if the type is nullable, add additional check to be not null if (Nullable.GetUnderlyingType(propertyExp.Type) != null) { var propertyNotNullExpr = Expression.NotEqual(propertyExp, Expression.Constant(null, propertyExp.Type)); return(Expression.AndAlso(propertyNotNullExpr, propertyContainsExpr)); } return(propertyContainsExpr); }
/// <summary> /// Sets the string match method. Useful only for string properties. Default is String.Contains() /// </summary> /// <param name="method"></param> /// <returns></returns> public ApplyToQueryOptions <T> UseStringMatchMethod(StringMatchMethod method) { options[currentKey].StringMatchMethod = method; return(this); }