Files
Generic.CL/Services/FilterExtension.cs
T

127 lines
4.6 KiB
C#

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<T> ApplyFilter<T, TFilter>(this IQueryable<T> 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<Func<T, bool>>(finalExpression, parameter);
query = query.Where(lambda);
}
return query;
}
}