我正在尝试获取此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)))
答案 0 :(得分:0)
在不知道完整变量的情况下很难复制代码。我认为你的错误在于你对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。