2010-07-30 24 views
27

我建立一个LINQ表达式树,但它不会编译,因为涉嫌局部变量$var1超出范围:构建LINQ表达式树:如何让变量范围

可变“”

.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 
} 
:类型System.Object的“从范围 '' 引用,但它没有定义

这是表达式树的10

以下代码负责构建树。它是更大的一部分,因此我不希望它的目的从这个例子中清晰可见。

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

所以问题是:我如何获得本地变量的范围,使表达式编译成功?

回答

42

傻冒加入Expression.Variable到在块“正常”的表情列表 - 你应该use the overload which specifies the variables do declare for the block separately

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

(和删除调用expressions.Add(resultVariable);

+0

感谢乔恩,那工作!解决这个问题揭示了第二个类似的问题。 sourceExpression变量的赋值会导致表达式编译器抛出:'范围'引用'TestClass'的变量'n',但它没有被定义“ – 2010-07-30 11:46:42

+0

我能够解决这个问题,再次感谢。 – 2010-08-02 08:29:14

+1

再次感谢您的帮助。这个问题与我写在http://blog.subspace.nl/post/Getting-rid-of-null-checks-in-property-chains.aspx上的一篇博文有很大的关系,这可能会让你感兴趣。 – 2010-08-05 21:19:56