构建C#EntityFramework IQueryable表达式时出现问题

所以我正在尝试构建一个半复杂的搜索表达式,但我不得不尝试创建一个基本的。 用于getValueExpression的表达式如下所示:

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的值以与要搜索的值进行比较。 任何帮助或领导正确的方向将不胜感激。

 public static IQueryable Search(this IQueryable source, Expression<Func> getValueExpression, string searchOption, string searchValue) { var searchValueExpression = Expression.Constant(searchValue); var comparisonExpression = Expression.Equal(getValueExpression, searchValueExpression); var lambdaExpression = Expression.Lambda<Func>(comparisonExpression); return source.Where(lambdaExpression); } 

我尝试过类似这样的事情,但遇到了错误的参数金额exception:

 var getValueExpressionValue = Expression.Call(getValueExpression.Compile().Method, parameterValueExpression); 

这是一个让你组成表达式的方法; 也就是说你可以使用一个表达式的输出作为另一个表达式的输入,创建一个新表达式,获取第一个表达式的输入和第二个表达式的输出:

 public static Expression> Compose( this Expression> first, Expression> 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>(newSecond, param); } 

其中使用以下方法将一个表达式替换为另一个表达式:

 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 Search(this IQueryable source, Expression> getValueExpression, string searchOption, string searchValue) { var predicate = getValueExpression.Compose(value => value == searchValue); return source.Where(predicate); } 

以下是如何做到这一点:

 public static IQueryable Search(this IQueryable source, Expression> getValueExpression, string searchOption, string searchValue) { // const searchValue var searchValueExpression = Expression.Constant(searchValue); // parameter x var parameterExpression = Expression.Parameter(typeof(TSource)); // func(x) var parameterGetValueExpression = Expression.Invoke(getValueExpression, parameterExpression); // func(x) == searchValue var comparisonExpression = Expression.Equal(parameterGetValueExpression, searchValueExpression); // x => func(x) == searchValue var lambdaExpression = Expression.Lambda>(comparisonExpression, parameterExpression); return source.Where(lambdaExpression); }