public static Expression Equals(Expression memberExpression, Expression searchFor, SearchIntent searchIntent) { if (searchIntent == SearchIntent.Undefined) { throw new ArgumentException($"{nameof(searchIntent)} cannot be Undefined", nameof(searchIntent)); } if (searchFor.Type != typeof(string)) { return(Equal(memberExpression, searchFor)); } return(searchIntent == SearchIntent.Database ? GetDatabaseStringEquals(memberExpression, searchFor) : GetInMemoryStringEquals(memberExpression, searchFor)); }
public static Expression Match(Expression memberExpression, object searchValue, SearchIntent searchIntent) { string matchText = searchValue?.ToString() ?? string.Empty; const char wildcardChar = '*'; string wildcardString = wildcardChar.ToString(); bool matchTextStartsWithWildCard = matchText.StartsWith(wildcardString); bool matchTextEndsWithWildCard = matchText.EndsWith(wildcardString); if (matchTextStartsWithWildCard && matchTextEndsWithWildCard) { return(Contains(memberExpression, Expression.Constant(matchText.Trim(wildcardChar)), searchIntent)); } if (matchTextStartsWithWildCard) { return(EndsWith(memberExpression, Expression.Constant(matchText.TrimStart(wildcardChar)), searchIntent)); } if (matchTextEndsWithWildCard) { return(StartsWith(memberExpression, Expression.Constant(matchText.TrimEnd(wildcardChar)), searchIntent)); } return(Equals(memberExpression, Expression.Constant(matchText), searchIntent)); }
public static Expression EndsWith(Expression memberExpression, Expression searchFor, SearchIntent searchIntent) { if (memberExpression.Type != searchFor.Type) { throw new ArgumentException($"{nameof(memberExpression)} and {nameof(searchFor)} must be expressions of same type. {nameof(memberExpression)} is of type {memberExpression.Type.ToPrettyString()} and {nameof(searchFor)} is of type {searchFor.Type.ToPrettyString()}."); } if (memberExpression.Type != typeof(string)) { throw new ArgumentException($"{nameof(Contains)} can be used for strings only."); } return(searchIntent == SearchIntent.Database ? GetDatabaseEndsWith(memberExpression, searchFor) : GetInMemoryEndsWith(memberExpression, searchFor)); }
private static Expression ExpressionFromFieldComparerGroup <T>(FieldComparerGroup fieldComparerGroup, ParameterExpression param, SearchIntent searchIntent) where T : class { Expression search = null; foreach (FieldComparer fieldComparer in fieldComparerGroup.FieldComparers) { // The expression tree we are building PropertyInfo propertyInfo = GetPropertyWithValidation <T>(fieldComparer.FieldName); if (propertyInfo == null) { throw new Exception($"The column '{fieldComparer.FieldName}' does not exist in my dataclass"); } object convertedSearchValue = GetConvertedSearchValue(propertyInfo, fieldComparer); Expression searchWithType; // ReSharper disable once PossibleNullReferenceException if (propertyInfo.PropertyType == typeof(Guid) && Guid.Empty.Equals((Guid)convertedSearchValue)) { searchWithType = Expression.Field(null, typeof(Guid), "Empty"); convertedSearchValue = Guid.Empty; } else { searchWithType = Expression.Constant(convertedSearchValue); } MemberExpression memberExpression = Expression.PropertyOrField(param, fieldComparer.FieldName); Expression body; switch (fieldComparer.Operator) { case CompareOp.Equals: body = SearcherExpressionExtensions.Equals(memberExpression, searchWithType, searchIntent); break; case CompareOp.NotEquals: body = SearcherExpressionExtensions.NotEqual(memberExpression, searchWithType); break; case CompareOp.GreaterThanOrEqual: body = SearcherExpressionExtensions.GreaterThanOrEqual(memberExpression, searchWithType); break; case CompareOp.LessThanOrEqual: body = SearcherExpressionExtensions.LessThanOrEqual(memberExpression, searchWithType); break; case CompareOp.LessThan: body = SearcherExpressionExtensions.LessThan(memberExpression, searchWithType); break; case CompareOp.GreaterThan: body = SearcherExpressionExtensions.GreaterThan(memberExpression, searchWithType); break; //case CompareOp.EqualsCaseSensitive: // body = SearcherExpressionExtensions.Equal(memberExpression, searchWithType); // break; case CompareOp.StartsWith: body = SearcherExpressionExtensions.StartsWith(memberExpression, searchWithType, searchIntent); break; //case CompareOp.StartsWithCaseSensitive: // body = SearcherExpressionExtensions.StartsWith(memberExpression, searchWithType); // break; case CompareOp.Contains: body = SearcherExpressionExtensions.Contains(memberExpression, searchWithType, searchIntent); break; //case CompareOp.ContainsCaseSensitive: // body = SearcherExpressionExtensions.Contains(memberExpression, searchWithType); // break; case CompareOp.EndsWith: body = SearcherExpressionExtensions.EndsWith(memberExpression, searchWithType, searchIntent); break; //case CompareOp.EndsWithOrdinalIgnoreCase: // body = SearcherExpressionExtensions.EndsWithOrdinalIgnoreCase(memberExpression, searchWithType); // break; case CompareOp.Match: body = SearcherExpressionExtensions.Match(memberExpression, convertedSearchValue, searchIntent); break; default: throw new Exception($"Search term {fieldComparer.Operator} not supported"); } if (search == null) { search = body; } else { search = fieldComparerGroup.Operator == LogicalOp.And ? Expression.AndAlso(search, body) : Expression.OrElse(search, body); } } foreach (FieldComparerGroup subFieldComparerGroup in fieldComparerGroup.FieldComparerGroups) { var subExpression = ExpressionFromFieldComparerGroup <T>(subFieldComparerGroup, param, searchIntent); if (search == null) { search = subExpression; } else { search = fieldComparerGroup.Operator == LogicalOp.And ? Expression.AndAlso(search, subExpression) : Expression.OrElse(search, subExpression); } } return(search ?? Expression.Constant(true)); }
public static IEnumerable <T> Filter <T>(this IEnumerable <T> items, SearchQuery searchQuery, SearchIntent searchIntent) where T : class { if (searchQuery.GroupBy.Count > 0) { throw new NotSupportedException($"{nameof(searchQuery.GroupBy)} is not supported for filtering {nameof(SearchQuery)}."); } Func <T, bool> predicate = CreateSearchExpression <T>(searchQuery, searchIntent).Compile(); items = items .Where(predicate) .OrderBy(searchQuery.OrderBy); if (searchQuery.Skip > 0) { items = items.Skip(searchQuery.Skip); } if (searchQuery.Take > 0) { items = items.Take(searchQuery.Take); } return(items); }
public static Expression <Func <T, bool> > CreateSearchExpression <T>(SearchQuery searchQuery, SearchIntent searchIntent) where T : class { ParameterExpression param = Expression.Parameter(typeof(T)); Expression search = ExpressionFromFieldComparerGroup <T>(searchQuery, param, searchIntent); return(Expression.Lambda <Func <T, bool> >(search, param)); }