Trouble with building a C# EntityFramework IQueryable Expression

落花浮王杯 提交于 2019-11-28 13:57:58

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);
}

This lets you write:

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);
}

Here is how you can do it :

public static IQueryable<TSource> Search<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, string>> 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<Func<TSource, bool>>(comparisonExpression, parameterExpression);

    return source.Where(lambdaExpression);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!