Costruire un albero di espressioni LINQ: come ottenere variabili nell'ambito

.net c# expression-trees lambda linq

Domanda

Sto costruendo un albero di espressioni LINQ ma non verrà compilato perché presumibilmente la variabile locale $var1 è fuori ambito:

variabile '' di tipo 'System.Object' referenziata dall'ambito '', ma non è definita

Questo è l'albero delle espressioni:

.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
}

Il seguente codice è responsabile della costruzione dell'albero. Fa parte di qualcosa di più grande, quindi non mi aspetto che il suo scopo sia perfettamente chiaro da questo esempio.

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

Quindi la domanda è: come faccio ad avere la variabile locale in scope in modo che l'espressione compili con successo?

Risposta accettata

Aggiungendo Expression.Variable alla lista di espressioni "normali" nel blocco - dovresti usare l'overload che specifica le variabili dichiarate per il blocco separatamente :

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

(E rimuovere la chiamata alle expressions.Add(resultVariable); )



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché