2015-01-11 28 views
2

我試圖讓這個LINQ表達式:變量是從範圍內引用,但不能定義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

你真的需要解釋更多的問題和原因。構建表達式樹依賴於如何處理'_WhereExpressions',表達式在哪裏編譯等。 – Shlomo

回答

0

這是很難不知道完整的變量複製代碼。我認爲你的錯誤在於你對Expression.Parameter的理解。這主要用於將顯式參數傳遞到lambda中:在您的示例中,是應該使用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

相關問題