我很难让这种方法正常工作。我的目标是使用实体框架 (EF) 创建一个通用函数,该函数可以使用过滤器、包含和分页来搜索数据库。
我的困难在于过滤器。我想分析每种类型的变量;例如,仅在字符串不同于 null 或空时过滤字符串,在 guid 与 Guid.Empty 不同时过滤字符串,等等。
public virtual async Task<PageFilter<TEntity>> GetWithFilterAndPagination(
BaseRequestFilter pagination,
List<Expression<Func<TEntity, object>>> includes,
List<Expression<Func<TEntity, bool>>> filters)
{
try
{
using (var dbContext = IntegramillDbContextFactory.Create())
{
var query = dbContext.Set<TEntity>().AsQueryable();
if (includes != null && includes.Any())
{
foreach (var include in includes)
{
query = query.Include(include);
}
}
if (filters != null && filters.Any())
{
foreach (var filter in filters)
{
query = query.Where(filter);
}
}
var totalCount = query.Count();
if (pagination.Offset != null)
query = query.Skip((int)pagination.Offset);
if (pagination.Take > 0)
query = query.Take(pagination.Take);
return new PageFilter<TEntity>(query.ToList(), totalCount);
}
}
catch (Exception e)
{
Log.Error(e, "<{EventoId}> - Erro ao CONSULTAR " + typeof(TEntity).Name, "RepositoryError");
throw e;
}
}
我已经尝试过这个但无法正常工作
var parameter = Expression.Parameter(typeof(TEntity), "x");
var expressaoBinaria = (BinaryExpression)filter.Body;
var propriedade = (MemberExpression)expressaoBinaria.Left;
var valor = expressaoBinaria.Right.ToObject();
var valor2 = expressaoBinaria.Right.ToString();
var valor3 = (MemberExpression)expressaoBinaria.Right;
var tipoDaPropriedade = propriedade.Type;
if (tipoDaPropriedade == typeof(string))
{
var teste2 = (string)valor2;
await Console.Out.WriteLineAsync("testeString");
}
if (tipoDaPropriedade == typeof(int))
{
var teste2 = int.Parse(valor2);
await Console.Out.WriteLineAsync("teste");
}
考虑到这些扩展方法:
public static class StringExt {
public static bool IsNullOrEmpty(this string s) => String.IsNullOrEmpty(s);
}
public static class ExpressionExt {
public static TResult Value<TResult>(this Expression e) => (TResult)((e is ConstantExpression c) ? c.Value : Expression.Lambda(e).Compile().DynamicInvoke());
}
您可以使用以下方法测试过滤器的 RHS:
var r = (filter.Body as BinaryExpression)?.Right;
var t = r?.Type;
if (t == typeof(string) && !r.Value<string>().IsNullOrEmpty())
q = q.Where(filter);
else if (t == typeof(Guid) && r.Value<Guid>() != Guid.Empty)
q = q.Where(filter);
请注意,如果过滤器不是预期的格式(例如,带有简单二进制表达式且 LHS 为参数的 lambda),那么它将被忽略。
也并不是说这不太可能很快,因为它使用
LambdaExpression.Compile()
来计算 RHS 的值。