using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using static System.Linq.Expressions.Expression; namespace PartSource.Services.Extensions { public static class IQueryableExtensions { public static IQueryable ApplyQueryDto(this IQueryable queryable, T dto) { foreach (PropertyInfo property in typeof(T).GetProperties()) { object value = property.GetValue(dto); if (IsFilterableValue(value)) { queryable = queryable.Where(property, value); } } return queryable; } private static IQueryable Where(this IQueryable queryable, PropertyInfo property, object value) { if (property == null || value == null) { return queryable; } MemberExpression functions = Property(null, typeof(EF).GetProperty(nameof(EF.Functions))); MethodInfo likeMethodInfo = typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.Like), new Type[] { functions.Type, typeof(string), typeof(string) }); ParameterExpression lambdaParameter = Parameter(typeof(T), "x"); Expression expressionProperty = Property(lambdaParameter, property.Name); if (property.PropertyType != typeof(string)) { expressionProperty = Call(expressionProperty, typeof(object).GetMethod(nameof(object.ToString), new Type[0])); } MethodCallExpression methodCall = Call( null, likeMethodInfo, functions, expressionProperty, Constant(value.ToString())); return queryable.Where(Lambda>(methodCall, lambdaParameter)); } private static bool IsFilterableValue(object value) { switch (value) { case int i: if (i == default) return false; break; case DateTime d: if (d == default) return false; break; case string s: if (string.IsNullOrEmpty(s)) return false; break; default: if (value == null) return false; break; } return true; } } }