一種方法是採取的事實,即調用上期待Expression<Func<...>>
.NET類型方法時,F#會自動執行這種轉換。
我不完全確定何時將其添加到語言中,但肯定使用F#4,您不需要將F#表達式顯式轉換爲LINQ。如果你想這樣做擺在首位的原因是能夠使用LINQ IQueryable
的API(或其他基於表達式的.NET的API),那麼它現在只是沒有努力的工作,如:
someEfDataContext.MyEntities.Single(fun e -> e.Id = 42)
剛作品。儘管這看起來像一個普通的lambda(我們還沒有使用F#的表達式語法),但是它編譯爲生成F#表達式對象的代碼,然後將其傳遞給LeafExpressionConverter.QuotationToExpression
以將它轉換爲LINQ表達式對象。
但有時您會想直接在F#中獲得LINQ樣式表達式對象。 (例如,有時它是有用的編寫產生,你會在多個查詢使用表達式的F#功能。)在這種情況下,你可以寫這樣的幫手:
type FunAs() =
static member LinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e
這看起來像它什麼也不做 - 它只是返回它的參數。但是,因爲FunAs
是一個.NET類型,所以F#會自動編譯任何呼叫站點,該站點將fun
表達式調用到生成合適的LINQ查詢表達式的代碼中。例如: -
let linqExpr = FunAs.LinqExpression(fun (e:MyEntity) -> e.Id = 42)
這裏,linqExpr
將Expression<Func<MyEntity, bool>>
類型。
關鍵是這個方法是一個.NET類型的成員。如果您嘗試同樣的事情用一個普通的F#功能:
let funAsLinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e
這似乎像它應該是說完全一樣的東西FunAs.LinqExpression
,你會發現,你不能把它以同樣的方式。例如,如果你試試這個:
let linqExpr = funAsLinqExpression(fun (e:MyEntity) -> e.Id = 42)
你會得到一個(略無益的)錯誤:「這個函數的參數太多,或者在上下文中,其中一個功能不expected`使用。
通過使這個函數成爲.NET類型的成員,我們可以利用F#的有用的「你似乎在調用一個需要LINQ風格表達式的.NET API,讓我爲你處理這個問題」特徵。
(這有可能是有要求的LINQ編譯器不把.NET類型到圖片爲您執行這個同樣的伎倆,一些更明確的方式,但我還沒有發現它。)
哎,沒你找到一個更簡單的方法來做到這一點? – nicolas 2012-05-01 13:06:16
在旁註中,這裏有一個相關的問題,(雖然沒有引用,雖然)http://stackoverflow.com/questions/3392000/interop-between-f-and-c-sharp-lambdas – nicolas 2012-05-01 13:08:17