Building a LINQ expression tree: how to get variable in scope

13,686

Your'e adding the Expression.Variable to the list of "normal" expressions in the block - you should use the overload which specifies the variables do declare for the block separately:

Expression finalExpression = Expression.Block(new[] { resultVariable },
                                              expressions);

(And remove the call to expressions.Add(resultVariable);)

Share:
13,686
Sandor Drieënhuizen
Author by

Sandor Drieënhuizen

I'm a passionate software developer, working full-time as a freelancer and loving to work with (but not limited to) the many gems from the Microsoft Open Source Stack.

Updated on July 18, 2022

Comments

  • Sandor Drieënhuizen
    Sandor Drieënhuizen almost 2 years

    I'm building a LINQ expression tree but it won't compile because allegedly the local variable $var1 is out of scope:

    variable '' of type 'System.Object' referenced from scope '', but it is not defined

    This is the expression tree:

    .Block() {
        $var1;
        .If ($n.Property1 == null) {
            .Block() {
                $var1 = null;
                .Return #Label1 { }
            }
        } .Else {
            .Default(System.Void)
        };
        $var1 = (System.Object)($n.Property1).Length;
        .Label
        .LabelTarget #Label1:;
        $var1
    }
    

    The following code is responsible for building the tree. It is part of something larger, therefore I don't expect its purpose to be perfectly clear from this example.

    MemberExpression sourceExpression = ...;
    
    List<Expression> expressions = new List<Expression>();
    LabelTarget returnTarget = Expression.Label();
    ParameterExpression resultVariable = Expression.Variable(typeof(object));
    
    expressions.Add(resultVariable);
    
    expressions.Add(
        Expression.IfThen(
            Expression.Equal(sourceExpression, Expression.Constant(null)),
            Expression.Block(
                Expression.Assign(resultVariable, Expression.Constant(null)),
                Expression.Return(returnTarget))));
    
    expressions.Add(
        Expression.Assign(
            resultVariable,
            Expression.Convert(sourceExpression, typeof(object))));
    
    expressions.Add(Expression.Label(returnTarget));
    expressions.Add(resultVariable);
    
    Expression finalExpression = Expression.Block(expressions);
    object result = Expression.Lambda<Func<object>>(finalExpression).Compile()();
    

    So the question is: how do I get the local variable into scope so that the expression compiles succesfully?