我正在为我们这个庞大的项目创建一个更复杂的过滤系统。主要谓词之一是能够通过字符串参数传递比较。这以以下形式表示:“>50”或“5-10”或“
我有什么(作为例子来说明)
视图模型:
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
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,它建议我转换它改为布尔值......
我的脑子里现在充满了绒毛……
更新2:
我设法找到一种方法,让一段代码可以在控制台应用程序的内存存储库中运行。不过,我还没有尝试使用实体框架。
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:
是的,在坐下来再次查看 lambda 表达式之后,在最后一个答案之前,我想出了类似于以下内容的内容,它没有满足“Compare()”的确切要求,但它是一个“重载”其中方法:
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。不然的话……好吧,最后的回应可能就过去了。