构建 LINQ 表达式树:如何获取范围内的变量

Posted

技术标签:

【中文标题】构建 LINQ 表达式树:如何获取范围内的变量【英文标题】:Building a LINQ expression tree: how to get variable in scope 【发布时间】:2011-03-23 04:49:49 【问题描述】:

我正在构建一个 LINQ 表达式树,但它不会编译,因为据称局部变量 $var1 超出范围:

从范围“”引用的“System.Object”类型的变量“”,但未定义

这是表达式树:

.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

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

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

所以问题是:如何将局部变量放入作用域中,以便表达式编译成功?

【问题讨论】:

【参考方案1】:

您将 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);的调用)

【讨论】:

感谢乔恩,这很有效!解决这个问题揭示了第二个相当相似的问题。 sourceExpression 变量的赋值使表达式编译器抛出:“从范围''引用的'TestClass'类型的变量'n',但未定义” 再次感谢您帮助我。这个问题与我在blog.subspace.nl/post/… 写的一篇博文密切相关,这可能很有趣。 感谢您的链接。正是我需要了解 lambda 参数与块范围变量。

以上是关于构建 LINQ 表达式树:如何获取范围内的变量的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LINQ 从列表中选择提供的索引范围内的值

如何构建具有多个条件的 Lambda 表达式树

如何创建 LINQ 表达式树以选择匿名类型

构建 LINQ 表达式以查找与树节点的所有后代相关的项目

如何在 Angular 表达式中获取一种范围变量?

如何将字符串转换为其等效的 LINQ 表达式树?