1

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.

1
  • 1
    I don't see any local variables or assignments in the expression you're trying to create, so why are you trying to use them in your code? Commented Nov 7, 2013 at 8:17

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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

2 Comments

Thanks. That will work, but as this is my first experimentation with Expressions, I would like to know how to build it up myself to further my understanding. Thanks for pointing out the fault as well. I had your suggestion before and forgot to change it back before posting.
@peinearydevelopment If you want to learn what the compiler does, I suggest you look at what the compiler does with a decompiler such as IlSpy (turn off the option to decompile expressions).
1

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

4 Comments

You should be using Expression.Property to access a property, rather than calling the properties get method.
Indeed. The only exception is if you are accessing a non-public property, in which case you will need to use reflection to retrieve the accessor and Call it yourself.
Thanks. Updated to using Expression.Property.
I want to thank you all for the valuable input I really appreciate it. This is exactly what I was looking for!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.