using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Threading.Tasks; namespace Generic.Services; public static class FilterExtension { public static IQueryable ApplyFilter(this IQueryable query, TFilter filter) where TFilter : class { if (filter == null) return query; var parameter = Expression.Parameter(typeof(T), "x"); Expression finalExpression = null; var filterProperties = typeof(TFilter) .GetProperties() .Where(p => p.GetValue(filter) != null); foreach (var filterProperty in filterProperties) { var filterValue = filterProperty.GetValue(filter); if (filterValue == null) continue; var propertyName = filterProperty.Name; PropertyInfo entityProperty; Expression propertyExpression = null; Expression comparison = null; // Handle special suffix cases if (propertyName.EndsWith("_Start") || propertyName.EndsWith("_Min")) { entityProperty = typeof(T).GetProperty( propertyName.Substring(0, propertyName.LastIndexOf('_')) ); if (entityProperty != null) { propertyExpression = Expression.Property(parameter, entityProperty); comparison = Expression.GreaterThanOrEqual( propertyExpression, Expression.Constant(filterValue, entityProperty.PropertyType) ); } } else if (propertyName.EndsWith("_End") || propertyName.EndsWith("_Max")) { entityProperty = typeof(T).GetProperty( propertyName.Substring(0, propertyName.LastIndexOf('_')) ); if (entityProperty != null) { propertyExpression = Expression.Property(parameter, entityProperty); comparison = Expression.LessThanOrEqual( propertyExpression, Expression.Constant(filterValue, entityProperty.PropertyType) ); } } else if (propertyName.EndsWith("Name", StringComparison.OrdinalIgnoreCase)) { entityProperty = typeof(T).GetProperty(propertyName); if (entityProperty != null && entityProperty.PropertyType == typeof(string)) { propertyExpression = Expression.Property(parameter, entityProperty); // For string Contains operation var containsMethod = typeof(string).GetMethod( "Contains", new[] { typeof(string) } ); var filterValueString = filterValue.ToString(); comparison = Expression.Call( propertyExpression, containsMethod, Expression.Constant(filterValueString, typeof(string)) ); } else if (entityProperty != null) { // Fall back to equality comparison if it's not a string propertyExpression = Expression.Property(parameter, entityProperty); comparison = Expression.Equal( propertyExpression, Expression.Constant(filterValue, entityProperty.PropertyType) ); } } else { entityProperty = typeof(T).GetProperty(propertyName); if (entityProperty != null) { propertyExpression = Expression.Property(parameter, entityProperty); comparison = Expression.Equal( propertyExpression, Expression.Constant(filterValue, entityProperty.PropertyType) ); } } if (comparison != null) { finalExpression = finalExpression == null ? comparison : Expression.AndAlso(finalExpression, comparison); } } if (finalExpression != null) { var lambda = Expression.Lambda>(finalExpression, parameter); query = query.Where(lambda); } return query; } }