private static void AppendFieldComparers <TItem>(FieldComparerGroup <TItem> sourceFieldComparerGroup, FieldComparerGroup destinationFieldComparerGroup) where TItem : class { if ((sourceFieldComparerGroup.Terms.Count() > 1) && (sourceFieldComparerGroup.Operator == LogicalOp.None)) { throw new ArgumentException($"The logical operator may not be {nameof(LogicalOp.None)} when more than one term is specified!"); } foreach (SearchTerm <TItem> sourceSearchTerm in sourceFieldComparerGroup.Terms) { FieldComparer <TItem> fieldComparer = sourceSearchTerm as FieldComparer <TItem>; if (fieldComparer != null) { destinationFieldComparerGroup.FieldComparers.Add(new FieldComparer { FieldName = fieldComparer.FieldName, Operator = fieldComparer.Operator, CompareValue = fieldComparer.CompareValue }); } else { FieldComparerGroup <TItem> sourceSubFieldComparerGroup = sourceSearchTerm as FieldComparerGroup <TItem>; if (sourceSubFieldComparerGroup != null) { var destinationSubFieldComparerGroup = new FieldComparerGroup { Operator = sourceSubFieldComparerGroup.Operator }; AppendFieldComparers(sourceSubFieldComparerGroup, destinationSubFieldComparerGroup); if (destinationSubFieldComparerGroup.FieldComparers.Count + destinationSubFieldComparerGroup.FieldComparerGroups.Count > 0) { destinationFieldComparerGroup.FieldComparerGroups.Add(destinationSubFieldComparerGroup); } } else { throw new ArgumentException($"Unknown search term: {sourceSearchTerm?.GetType()}"); } } } }
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)); }