Метод расширения, возвращающий лямбда-выражение через сравнение

Я занимаюсь созданием более сложной системы фильтрации для нашего огромного проекта. Одним из основных предикатов является возможность передавать сравнения через строковый параметр. Это выражается в следующей форме: ">50" или "5-10" или "<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)

. Возможно, это даже неправильно, но это все, что у меня есть. Построитель сравнения не проблема, это просто. Сложная часть на самом деле возвращает выражение. Я никогда не пытался возвращать выражения как значения функций. Так что в основном мне нужно сохранить поле и вернуть выражение сравнения, в значительной степени.

Есть помощь? :x

Обновление:

Увы, это не решает мою проблему. Это может быть потому, что я не спал последние 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);
}

В ней отсутствует "это что-то-значение" для сравнения в первую очередь, и мне не удалось еще разберитесь, как сделать так, чтобы он мог получить входное выражение... что касается ReSharper, он предлагает мне вместо этого преобразовать его в логическое значение...

В данный момент моя голова полна ерунды...

Обновление 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);
    }

Тем не менее, я очень сомневаюсь, что это то, что мне нужно

Обновление 3:

Верно, после того, как я сел и снова просмотрел лямбда-выражения, прежде чем дать последний ответ, я пришел к чему-то вроде следующего: он не соответствует точным требованиям «Сравнить ()», но это «перегруженный» метод Where:

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. В противном случае... ну, последний ответ, вероятно, пойдет.

8
задан NeroS 15 May 2012 в 18:19
поделиться