127 lines
4.6 KiB
C#
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;
|
|
}
|
|
}
|