Метод расширения, возвращающий лямбда-выражение через сравнение
Я нахожусь в процессе создания более сложной системы фильтрации для этого нашего огромного проекта. Одним из основных предикатов является возможность передавать вычисления через строковый параметр. Это выражается в следующей форме: & quot; & gt; 50 & quot; или "5-10" или "& lt; 123,2"
Что я имею (как пример для иллюстрации)
ViewModel:
TotalCost (string) (value: "<50")
Required (string) (value: "5-10")
EF Модель:
TotalCost (double)
Required(double)
Выражение, которое я хотел бы использовать:
model => model.Where(field => field.TotalCost.Compare(viewModel.TotalCost) && field.Required.Compare(viewModel.Required));
Выражение, которое я хотел бы получить:
model => model.Where(field => field.TotalCost < 50 && field.Required > 5 && field.Required < 10);
Или что-то похожее на это
Однако ... я понятия не имею, с чего начать. Я сузил это до
public static Expression Compare<T>(this Expression<Func<T, bool>> value, string compare)
Возможно, это даже не правильно, но это все, что у меня есть. Построение сравнения - это не проблема, это легкая задача. Трудная часть на самом деле возвращает выражение. Я никогда не пытался вернуть выражения в виде значений функций. Так что, в основном, мне нужно сохранить поле и вернуть выражение сравнения.
Любая помощь? :Икс
Update:
Увы, это не решает мою проблему. Это может быть потому, что я проснулся последние 23 часа, но я не имею ни малейшего понятия о том, как превратить его в метод расширения. Как я уже сказал, то, что мне нравится ... это в основном способ написать:
var ex = new ExTest();
var items = ex.Repo.Items.Where(x => x.Cost.Compare("<50"));
То, как я определил эту функцию (возможно, совершенно неправильно)
public static Expression<Func<decimal, bool>> Compare(string arg)
{
if (arg.Contains("<"))
return d => d < int.Parse(arg);
return d => d > int.Parse(arg);
}
В нем отсутствует значение "this-something-value" сравнивать с во-первых, и мне пока не удалось выяснить, как заставить его получать входные выражения ... что касается ReSharper, он предлагает вместо этого преобразовать его в логическое значение ...
Моя голова полна пуха в данный момент ...
Update 2:
Мне удалось найти способ получить кусок кода, который работает в хранилище памяти в консольном приложении. Я пока еще не попробовал это с 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);
}
Однако я очень сомневаюсь, что это то, что я после
Update 3:
Верно, после того, как я снова сел и посмотрел лямбда-выражения, перед последним ответом я придумал что-то похожее на следующее: оно не соответствует точным требованиям & quot; Сравнить () & quot; но это 'перегрузка-иш'; Где метод:
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);
}
Однако, несмотря на мои глаза, все кажется логичным, я получаю исключение времени выполнения:
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)
Это существо виновника, очевидно:
var lambda =
Expression.Lambda<Func<T, bool>>(Expression.LessThan(predicate.Body, Expression.Constant(double.Parse(50.ToString()))));
Я очень близок к решению. Если я смогу избавиться от этой ошибки, я верю, что EF сможет перевести ее на SQL. В противном случае ... ну, последний ответ, вероятно, пойдет.