Sono in procinto di creare un sistema di filtro più elaborato per questo nostro enorme progetto. Uno dei principali predicati è essere in grado di passare confronti attraverso un parametro stringa. Questo esprime nella forma seguente: "> 50" o "5-10" o "< 123,2"Metodo di estensione che restituisce espressione lambda tramite confronto
Quello che ho (come esempio per illustrare)
ViewModel:
TotalCost (string) (value: "<50")
Required (string) (value: "5-10")
EF Modello:
TotalCost (double)
Required(double)
Espressione che vorrei utilizzare:
model => model.Where(field => field.TotalCost.Compare(viewModel.TotalCost) && field.Required.Compare(viewModel.Required));
Espressione che vorrei ricevere:
model => model.Where(field => field.TotalCost < 50 && field.Required > 5 && field.Required < 10);
O qualcosa di simile a quello
Tuttavia ... non ho idea da dove cominciare. L'ho ristretto a
public static Expression Compare<T>(this Expression<Func<T, bool>> value, string compare)
Potrebbe non essere nemmeno corretto, ma questo è tutto ciò che ho. Il builder di confronto non è il problema, è facile. La parte difficile sta effettivamente restituendo l'espressione. Non ho mai provato a restituire espressioni come valori di funzione. Quindi in pratica quello che devo mantenere, è il campo e restituisco un'espressione di confronto, praticamente.
Qualsiasi aiuto? : X
Aggiornamento:
Purtroppo questo non risolve il problema. Può essere perché sono stato nelle ultime 23 ore, ma non ho il minimo indizio su come trasformarlo in un metodo di estensione. Come ho detto, quello che vorrei ... è fondamentalmente un modo di scrivere:
var ex = new ExTest();
var items = ex.Repo.Items.Where(x => x.Cost.Compare("<50"));
Il modo in cui ho sagomato che la funzione (probabilmente completamente sbagliata) è
public static Expression<Func<decimal, bool>> Compare(string arg)
{
if (arg.Contains("<"))
return d => d < int.Parse(arg);
return d => d > int.Parse(arg);
}
manca il " questo "valore-qualcosa" da confrontare al primo posto, e non sono ancora riuscito a capire come poter essere in grado di ottenere un input di espressione ... come per ReSharper, mi suggerisce di convertirlo in booleano invece ...
La mia testa è piena di pelucchi al momento ...
Aggiornamento 2:
sono riuscito a trovare un modo per avere un pezzo di codice che funziona in un repository di memoria su un applicazione console. Devo ancora provarlo con Entity Framework però.
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);
}
Tuttavia, dubito fortemente che è quello che sto dopo
Update 3:
Destra, dopo seduto e guardando attraverso le espressioni lambda di nuovo, prima che l'ultima risposta, mi è venuto con qualcosa di simile al seguente, non soddisfa i requisiti esatti di "Compare()" ma è un "overload-ish" Dove metodo:
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);
}
Tuttavia, nonostante ai miei occhi, tutto sembrava logico, ottengo un'eccezione di runtime di:
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)
Questa è la linea colpevole, ovviamente:
var lambda =
Expression.Lambda<Func<T, bool>>(Expression.LessThan(predicate.Body, Expression.Constant(double.Parse(50.ToString()))));
Sono molto vicino alla soluzione. Se riesco a togliermi quell'errore dalle spalle, credo che EF dovrebbe essere in grado di tradurlo in SQL. Altrimenti ... beh, probabilmente arriverà l'ultima risposta.
credo, che la vostra parte Update2 non verrà eseguito in SQL Server (EF). Hai provato? –
Sì, l'ho fatto. Come avrei pensato tbh. – NeroS