How do I create a lambda expression using return value from another lambda expression?

c# entity-framework expression-trees lambda linq-expressions

Question

The query "Convert Linq expression oeobj => obj.Prop into parent => parent.obj.Prop" has a different question and answer. The quantity of duplicate modifications with control difficulties is the only duplication I've recently seen on this site.

I'm trying to create an extension method for Entity Framework that, if the supplied value is not null or whitespace, adds a "Contains" call to a field. The if statement tests for null or whitespace were omitted out of sheer laziness.

I want to be able to use it as follows:

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

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

I've thought about this, but it's clear that the Invoke interferes with EF. What's the secret to utilizing a lambda's result while creating an expression?

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

The return might be as easy as: if it were just a delegate rather than a lambda.

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

That's what I want to achieve.

1
0
6/18/2018 8:16:08 PM

Accepted Answer

You want to utilize the body as the expression and take the argument from the lambda. You are choosing the expression tree and arguments from the lambda, not utilizing it at all as a 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;
    }
0
6/18/2018 7:52:03 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow