我正在为我们这个庞大的项目创建一个更精细的过滤系统。主要谓词之一是能够通过字符串参数传递比较。这以以下形式表示:“>50”或“5-10”或“<123.2”
我有什么(作为一个例子来说明)
视图模型:
TotalCost (string) (value: "<50")
Required (string) (value: "5-10")
英孚型号:
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);
}
它缺少首先要比较的“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。否则......好吧,最后的回应可能会消失。