问题描述
所以我正在尝试构建一个半复杂的搜索表达式,但我一直在尝试创建一个基本的表达式.用于 getValueExpression 的表达式类似于:
So I'm attempting to build a semi complication Search expression, but I'm stuck trying to create a basic one. The expressions being used for getValueExpression look something like:
x => x.PropertyA != null ? x.PropertyA.ToShortDateString() : "" //nullable datetime
x => x.PropertyB //string property
x => x.PropertyC != null x.PropertyC.ToString() : "" //nullable int
这是我的函数代码,当 getValueExpression 的类型为 Func 时出现错误,无法与字符串进行比较,这很有意义,我明白为什么会这样,但我无法弄清楚如何制作一个表达式,它获取 getValueExpression 的值以与正在搜索的值进行比较.任何帮助或正确方向的线索将不胜感激.
Here is my function code, it currently errors when getValueExpression being of type Func that can't be compared to a string, which makes perfect sense and I understand why that is, but I'm having trouble figuring out how to make an expression that gets the value of getValueExpression to compare to the value being searched for. Any help or leads in the right direction would be greatly appreciated.
public static IQueryable<TSource> Search<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, string>> getValueExpression, string searchOption, string searchValue)
{
var searchValueExpression = Expression.Constant(searchValue);
var comparisonExpression = Expression.Equal(getValueExpression, searchValueExpression);
var lambdaExpression = Expression.Lambda<Func<TSource, bool>>(comparisonExpression);
return source.Where(lambdaExpression);
}
我已经尝试过类似的事情,但是遇到了错误的参数数量异常的失败:
I've attempted similar things like this, but have met failure with incorrect arguments amount exception:
var getValueExpressionValue = Expression.Call(getValueExpression.Compile().Method, parameterValueExpression);
推荐答案
这里有一个方法可以让你编写表达式;也就是说,您可以将一个表达式的输出用作另一个表达式的输入,创建一个新表达式,获取第一个表达式的输入和第二个表达式的输出:
Here is a method that will let you compose expressions; that is to say you can use the output of one expression as the input of another, creating a new expression taking the input that the first takes and the output that the second takes:
public static Expression<Func<TFirstParam, TResult>>
Compose<TFirstParam, TIntermediate, TResult>(
this Expression<Func<TFirstParam, TIntermediate>> first,
Expression<Func<TIntermediate, TResult>> second)
{
var param = Expression.Parameter(typeof(TFirstParam), "param");
var newFirst = first.Body.Replace(first.Parameters[0], param);
var newSecond = second.Body.Replace(second.Parameters[0], newFirst);
return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}
它使用以下方法将一个表达式替换为另一个:
Which uses the following method to replace one expression with another:
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
这可以让你写:
public static IQueryable<TSource> Search<TSource>(this IQueryable<TSource> source,
Expression<Func<TSource, string>> getValueExpression,
string searchOption,
string searchValue)
{
var predicate = getValueExpression.Compose(value => value == searchValue);
return source.Where(predicate);
}
这篇关于构建 C# EntityFramework IQueryable 表达式时遇到问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!