2010-07-30 29 views
27

Tôi đang xây dựng một cây biểu thức LINQ nhưng nó sẽ không biên dịch vì bị cáo buộc các biến cục bộ $var1 là ra khỏi phạm vi:Xây dựng một cây biểu thức LINQ: làm thế nào để có được biến trong phạm vi

biến '' của loại 'System.Object' tham chiếu từ phạm vi '', nhưng nó không được định nghĩa

Đây là cây biểu thức:

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

Mã sau đây có trách nhiệm xây dựng cây. Nó là một phần của cái gì đó lớn hơn, do đó tôi không mong đợi mục đích của nó là hoàn toàn rõ ràng từ ví dụ này.

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

Câu hỏi đặt ra là: làm cách nào để biến biến cục bộ thành phạm vi để biểu thức biên dịch thành công?

Trả lời

42

Bạn đúng thêm Expression.Variable vào danh sách các biểu thức "bình thường" trong khối - bạn nên use the overload which specifies the variables do declare for the block separately:

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

(Và loại bỏ các cuộc gọi đến expressions.Add(resultVariable);)

+0

Cảm ơn Jon, mà làm việc! Giải quyết điều này cho thấy một vấn đề thứ hai, khá giống nhau. Việc gán biến sourceExpression làm cho trình biên dịch biểu thức ném: "biến 'n' của loại 'TestClass' được tham chiếu từ phạm vi '', nhưng nó không được xác định" –

+0

Tôi đã có thể khắc phục vấn đề đó, cảm ơn một lần nữa. –

+1

Cảm ơn bạn lần nữa vì đã giúp tôi. Câu hỏi liên quan chặt chẽ đến một bài đăng trên blog mà tôi đã viết tại http://blog.subspace.nl/post/Getting-rid-of-null-checks-in-property-chains.aspx có thể quan tâm. –

Các vấn đề liên quan