peinearydevelopment
peinearydevelopment

Reputation: 11474

Expression.Assign to assign Expression.Call to Expression.Variable

I have seen a number of similar posts and it seems as though the var1 I have declared seems to need to be passed in elsewhere, but I can't seem to figure it out.

public Expression<Func<ElementNode, bool>> CreateEqualNameExpression(string match)
{
    var parm = Expression.Parameter(typeof(ElementNode), "element");

    var expr = Expression.Call(parm, typeof(ElementNode).GetProperty("Name").GetGetMethod());
    var var1 = Expression.Variable(typeof(string), "elementName");
    var assign = Expression.Assign(var1, expr);

    var parm2 = Expression.Constant(match, typeof(string));

    var exp = Expression.Equal(assign, parm2);

    return Expression.Lambda<Func<ElementNode, bool>>(exp, new[] { parm });
}

basically I'm trying to create a method that represents

(ElementNode ele) => ele.Name == match;

but I'm having a really hard time coming up with the solution. Any help would be greatly appreciated.

I'm getting the error: 'elementName' of type 'System.STring' referenced from scope'', but it is not defined.

Upvotes: 1

Views: 833

Answers (3)

Shlomo
Shlomo

Reputation: 14370

As svick said, there's no need for the assignment:

public Expression<Func<ElementNode, bool>> CreateEqualNameExpression(string match)
{
    var parmExpr = Expression.Parameter(typeof(ElementNode));

    var propertyExpr = Expression.Property(parmExpr, "Name");
    var constExpr = Expression.Constant(match, typeof(string));

    var isEqualExp = Expression.Equal(propertyExpr, constExpr);

    return Expression.Lambda<Func<ElementNode, bool>>(isEqualExp , new[] { parmExpr });
}

Upvotes: 1

Mike Strobel
Mike Strobel

Reputation: 25623

As others have said, you do not actually need the intermediate variable, but seeing as you're trying to learn about expression trees, it's good information to know.

Local variables must be declared within a BlockExpression:

public Expression<Func<ElementNode, bool>> CreateEqualNameExpression(string match)
{
    var parm = Expression.Parameter(typeof(ElementNode), "element");

    var expr = Expression.Property(parm, "Name");
    var var1 = Expression.Variable(typeof(string), "elementName");
    var assign = Expression.Assign(var1, expr);

    var parm2 = Expression.Constant(match, typeof(string));

    var exp = Expression.Equal(var1, parm2);

    return Expression.Lambda<Func<ElementNode, bool>>(
        Expression.Block(new[] { var1 }, assign, exp),
        parm);
}

Which approximately creates:

element => { var elementName = element.Name; return elementName == <constant>; }

Note that I used the Property method to build a property accessor rather than using Call. This is the preferred way of accessing properties, unless the property is non-public.

Upvotes: 3

Will
Will

Reputation: 2542

Do you want the disgustingly easy version?

Expression.Lambda<Func<ElementNode, bool>> func = elem => elem.Name == match;

.Net will build the expression tree for you.


By the way, the code has a fault, it should be comparing var1 against the match (parm2), not 'assign'

var exp = Expression.Equal(var1, parm2);

Upvotes: 2

Related Questions