如何使用另一个lambda表达式的返回值创建lambda表达式?

时间:2018-06-18 18:10:31

标签: c# entity-framework lambda expression-trees linq-expressions

问题和答案都没有与“转换Linq表达式”obj => obj.Prop“进入”parent => parent.obj.Prop“”这个问题相同。我最近在这里发现的重复是带有控制问题的重复mod的数量。

我正在尝试为Entity Framework创建一个扩展方法,如果给定的值不为null或空格,则会在字段上添加“Contains”调用。它不是纯粹的懒惰,不希望所有if语句检查为null或空格。

我希望能够像这样使用它:

var qry = MyDb.Redacteds.OrderBy(a=>a.RedactedDate);

qry = qry.WhereContains(a => a.RedactedName, txtRedactedName.Text);

我已经想出了这个,但很明显,Invoke会导致EF出现问题。在构建表达式时使用lambda结果的诀窍是什么?

// create
// ent => exp(ent).Contains(s)
public static IQueryable<T> WhereContains<T>(this IQueryable<T> qry, Expression<Func<T, string>> exp, string s)
{
    if (!string.IsNullOrWhiteSpace(s))
    {
        s = s.Trim();
        var param = Expression.Parameter(typeof(T), "ent");;
        var call = Expression.Invoke(exp, param); // <-= HERE
        var body = Expression.Call(call, typeof(string).GetMethod("Contains", new[] { typeof(string) }), Expression.Constant(s));
        var lambda = Expression.Lambda<Func<T, bool>>(body, param);
        qry = qry.Where(lambda);
    }
    return qry;
}

如果它只是一个委托而不是一个lambda,那么返回很简单:

ent => exp(ent).Contains(s)

这就是我要做的事。

1 个答案:

答案 0 :(得分:0)

您想从lambda中获取参数并使用body作为表达式。您根本没有将它用作lambda - 您正在从lambda中选择表达式树和参数。

    // create
    // ent => exp(ent).Contains(s)
    public static IQueryable<T> WhereContains<T>(this IQueryable<T> qry, Expression<Func<T, string>> exp, string s)
    {
        if (!string.IsNullOrWhiteSpace(s))
        {
            s = s.Trim();

            //HERE GRAB THE PARAMETER
            var param = exp.Parameters[0];

            //HERE JUST USE EXP.BODY
            var body = Expression.Call(exp.Body, typeof(string).GetMethod("Contains", new[] { typeof(string) }), Expression.Constant(s));

            var lambda = Expression.Lambda<Func<T, bool>>(body, param);
            qry = qry.Where(lambda);
        }
        return qry;
    }