Método de extensão retornando a expressão lambda por meio de comparação
Estou no processo de criar um sistema de filtragem mais elaborado para este nosso enorme projeto. Um dos principais predicados é poder passar comparações através de um parâmetro de string. Isso expressa da seguinte forma: "> 50" ou "5-10" ou "<123.2"
O que eu tenho (como exemplo para ilustrar)
ViewModel:
TotalCost (string) (value: "<50")
Required (string) (value: "5-10")
Modelo EF:
TotalCost (double)
Required(double)
Expressão que eu gostaria de usar:
model => model.Where(field => field.TotalCost.Compare(viewModel.TotalCost) && field.Required.Compare(viewModel.Required));
Expressão que gostaria de receber:
model => model.Where(field => field.TotalCost < 50 && field.Required > 5 && field.Required < 10);
Ou algo parecido com isso
No entanto ... não tenho ideia de por onde começar. Eu reduzi-a a
public static Expression Compare<T>(this Expression<Func<T, bool>> value, string compare)
Pode não ser ainda correto, mas isso é tudo o que tenho. O construtor de comparação não é o problema, é o mais fácil. A parte difícil é, na verdade, retornar a expressão. Eu nunca tentei retornar expressões como valores de função. Então basicamente o que eu preciso manter, é o campo e retornar uma expressão de comparação, basicamente.
Qualquer ajuda? : x
Atualizar:
Infelizmente isso não resolve o meu problema. Pode ser porque eu tenho estado nas últimas 23 horas, mas não tenho a menor idéia de como fazer isso em um método de extensão. Como eu disse, o que eu gostaria ... é basicamente uma maneira de escrever:
var ex = new ExTest();
var items = ex.Repo.Items.Where(x => x.Cost.Compare("<50"));
A maneira que eu modelei essa função (provavelmente completamente errada) é
public static Expression<Func<decimal, bool>> Compare(string arg)
{
if (arg.Contains("<"))
return d => d < int.Parse(arg);
return d => d > int.Parse(arg);
}
Está faltando o "este -algo-valor" para comparar em primeiro lugar, e eu não consegui descobrir ainda como tê-lo ser capaz de obter uma entrada de expressão ... como para o ReSharper, isso sugere que eu converta -lo booleano em vez disso ...
Minha cabeça está cheia de cotão no momento ...
Atualização 2:
Eu consegui descobrir uma maneira de ter um pedaço de código que funciona em um repositório de memória em um aplicativo de console. Ainda estou tentando experimentá-lo com o Entity Framework.
public static bool Compare(this double val, string arg)
{
var arg2 = arg.Replace("<", "").Replace(">", "");
if (arg.Contains("<"))
return val < double.Parse(arg2);
return val > double.Parse(arg2);
}
No entanto, eu duvido que é o que eu estou depois
Atualização 3:
Certo, depois de sentar e olhar através das expressões lambda novamente, antes da última resposta, eu inventei algo parecido com o seguinte, ele não preenche os requisitos exatos de "Compare ()", mas é uma "sobrecarga-ish" Onde método:
public static IQueryable<T> WhereExpression<T>(this IQueryable<T> queryable, Expression<Func<T, double>> predicate, string arg)
{
var lambda =
Expression.Lambda<Func<T, bool>>(Expression.LessThan(predicate.Body, Expression.Constant(double.Parse(50.ToString()))));
return queryable.Where(lambda);
}
No entanto, apesar dos meus olhos, tudo parece lógico, eu recebo exceção de tempo de execução de:
System.ArgumentException was unhandled
Message=Incorrect number of parameters supplied for lambda declaration
Source=System.Core
StackTrace:
at System.Linq.Expressions.Expression.ValidateLambdaArgs(Type delegateType, Expression& body, ReadOnlyCollection`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, String name, Boolean tailCall, IEnumerable`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, Boolean tailCall, IEnumerable`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, ParameterExpression[] parameters)
Sendo esta a linha culpada, obviamente:
var lambda =
Expression.Lambda<Func<T, bool>>(Expression.LessThan(predicate.Body, Expression.Constant(double.Parse(50.ToString()))));
Estou muito perto da solução. Se eu conseguir esse erro, acredito que o EF seja capaz de traduzir isso em SQL. Caso contrário ... bem, a última resposta provavelmente irá.