【问题标题】:variable is referenced from scope, but not defined LINQ expression tree从范围引用变量,但未定义 LINQ 表达式树
【发布时间】:2015-03-09 11:53:36
【问题描述】:

我正在尝试获取此 LINQ 表达式:

Result = Result.Where(Function(Row) _WhereExpressions(0).InElements.Contains(Convert.ToString(Row(0))))

我有这个代码:

convertMethod = GetType(System.Convert).GetMethod("ToString", New Type() {GetType(Object)})
containsMethod = GetType(System.Collections.Generic.List(Of String)).GetMethod("Contains", New Type() {GetType(String)})
Dim listParameter = Expression.Parameter(GetType(List(Of String)), "_WhereExpressions(0).InElements")
expr = Expression.Call(whereMethod, Result.AsQueryable.Expression,
                     Expression.Lambda(Expression.Call(listParameter, containsMethod,
                     Expression.Call(convertMethod, Expression.ArrayAccess(rowParameter, Expression.Constant(index)))), rowParameter))

我得到了想要的表达式,但是如果我编译,我得到了错误:

variable '_WhereExpressions(0).InElements' of type 'System.Collections.Generic.List`1[System.String]' referenced from scope '', but it is not defined

_WhereExpressions(0).InElements 当然是声明的。

我该如何解决?

谢谢。

编辑:这是所有声明:

Dim whereMethod = GetType(Queryable).GetMethods(BindingFlags.Public Or BindingFlags.Static).First(Function(m) m.Name = "Where").MakeGenericMethod(GetType(Object()))
Dim convertMethod As MethodInfo = Nothing
Dim containsMethod As MethodInfo = Nothing
Dim rowParameter = Expression.Parameter(GetType(Object()), "Row")

_WhereExpressions(0).InElements 是一个简单的字符串列表,如下所示:

Dim idlist As New List(Of String)
idlist.Add("1")
idlist.Add("2")

我阅读了链接的帖子,但我真的不知道应该如何解决我的问题。

表达式树有很多功能,但对我来说看起来有点困难。

EDIT2:

这是一个例子,正是我想要实现的。只需复制并粘贴到 vs 中:

Dim dt As New DataTable
dt.Columns.Add("f1", Type.GetType("System.String"))
dt.Columns.Add("f2", Type.GetType("System.Int32"))
For i = 0 To 100
    dt.Rows.Add(i.ToString, i * 2)
Next
Dim indexes As New List(Of Integer)
indexes.Add(0)
indexes.Add(1)

Dim lst As New List(Of String)
lst.Add("10")
lst.Add("11")

Dim datarows As New List(Of DataRow)
For i = 0 To dt.Rows.Count - 1
    datarows.Add(dt.Rows(i))
Next

Dim result As IEnumerable(Of Object())
result = datarows.Select(Function(row) indexes.Select(Function(index) row(index)).ToArray)

'I would like this as an expression:
result = result.Where(Function(row) lst.Contains(Convert.ToString(row(0))))

EDIT3:我明白了:

Dim lst As Expression = Expression.Constant(list, GetType(System.Collections.Generic.List(Of String)))

【问题讨论】:

  • 你真的需要解释更多的方法和原因。构建表达式树取决于您要如何处理_WhereExpressions、表达式编译的位置等。

标签: vb.net linq expression-trees


【解决方案1】:

在不知道完整变量的情况下很难复制代码。我认为您的错误在于您对Expression.Parameter 的理解。这主要用作将显式参数传递给 lambda 的一种方式:在您的示例中,Row 是一个很好的示例,说明何时应该使用 Expression.Parameter_WhereExpressions 不是显式参数,它是一个变量,我假设它在您想要创建闭包的范围内。

您还应该注意,Expression.Parameter 方法的第二个变量是可选的,并且仅用于调试目的:如果您将其更改为:Expression.Parameter(GetType(List(Of String)), "Nonsense.nonsense"),您可能会看到错误消息相应地发生变化。

听起来您正试图在_WhereExpressions 周围引入闭包。使用原始表达式树,这是相当困难的。最简单的方法是将Expression.Constant 包裹在_WhereExpressions.InElements 周围。但是,如果在 _WhereExpressions 超出范围时执行编译表达式,就会遇到麻烦。见Issue with closure variable capture in c# expression

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多