zeroframework/Services/DeviceCenter/ZeroFramework.DeviceCenter.Infrastructure/Specifications/Extensions/SearchExtension.cs

68 lines
2.5 KiB
C#
Raw Permalink Normal View History

2023-12-05 09:22:48 +00:00
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;
using System.Reflection;
namespace ZeroFramework.DeviceCenter.Infrastructure.Specifications.Extensions
{
public static class SearchExtension
{
/// <summary>
/// Filters <paramref name="source"/> by applying an 'SQL LIKE' operation to it.
/// </summary>
/// <typeparam name="T">The type being queried against.</typeparam>
/// <param name="source">The sequence of <typeparamref name="T"/></param>
/// <param name="criterias">
/// <list type="bullet">
/// <item>Selector, the property to apply the SQL LIKE against.</item>
/// <item>SearchTerm, the value to use for the SQL LIKE.</item>
/// </list>
/// </param>
/// <returns></returns>
public static IQueryable<T> Search<T>(this IQueryable<T> source, IEnumerable<(Expression<Func<T, string>> selector, string searchTerm)> criterias)
{
Expression? expr = null;
var parameter = Expression.Parameter(typeof(T), "x");
foreach (var (selector, searchTerm) in criterias)
{
if (selector == null || string.IsNullOrEmpty(searchTerm))
{
continue;
}
PropertyInfo? propertyInfo = typeof(EF).GetProperty(nameof(EF.Functions));
if (propertyInfo is null)
{
continue;
}
var functions = Expression.Property(null, propertyInfo);
var like = typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.Like), new Type[] { functions.Type, typeof(string), typeof(string) });
if (like is null)
{
continue;
}
var propertySelector = ParameterReplacerVisitor.Replace(selector, selector.Parameters[0], parameter);
var expression = (propertySelector as LambdaExpression)?.Body;
if (expression is null)
{
continue;
}
var likeExpression = Expression.Call(null, like, functions, expression, Expression.Constant(searchTerm));
expr = expr == null ? likeExpression : Expression.OrElse(expr, likeExpression);
}
return expr == null ? source : source.Where(Expression.Lambda<Func<T, bool>>(expr, parameter));
}
}
}