Jednym ze sposobów można to zrobić teraz, aby skorzystać z faktu, że F # będą wykonywać tej konwersji automatycznie podczas wywoływania metody na .NET typów, które oczekują Expression<Func<...>>
.
Nie jestem całkowicie pewien, kiedy to zostało dodane do języka, ale na pewno z F # 4, nie musisz jawnie konwertować wyrażeń F # na LINQ. Jeśli powód, dla którego chciałem zrobić to w pierwszej kolejności miała być w stanie wykorzystać IQueryable
API LINQ (lub inne interfejsy API .NET w oparciu o wyrażenie) to teraz po prostu działa bez wysiłku, np:
someEfDataContext.MyEntities.Single(fun e -> e.Id = 42)
tylko Prace. Chociaż wygląda to jak zwykła lambda (nie używaliśmy składni wyrażeń F #), to kompiluje się do kodu, który tworzy obiekt ekspresyjny F #, a następnie przekazuje go do LeafExpressionConverter.QuotationToExpression
, aby przekształcić go w obiekt wyrażeń LINQ.
Ale czasami będziesz chciał uzyskać obiekt wyrażenia stylu LINQ bezpośrednio w F #. (Np, czasami warto jest napisać # funkcji F, która produkuje wyrażenie, które będzie używane w wielu zapytań.) W takim przypadku można napisać pomocnika takiego:
type FunAs() =
static member LinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e
To wygląda jakby nic nie robi - po prostu zwraca argument. Jednakże, ponieważ FunAs
jest typem .NET, F # automatycznie skompiluje dowolną stronę wywołania, która wywoła to z wyrażeniem fun
, do kodu, który generuje odpowiednie wyrażenie zapytania LINQ. Np .:
let linqExpr = FunAs.LinqExpression(fun (e:MyEntity) -> e.Id = 42)
Tutaj linqExpr
będzie od rodzaju Expression<Func<MyEntity, bool>>
.
Kluczem do tego jest to, że ta metoda należy do typu .NET. Jeśli spróbujesz dokładnie to samo ze zwykłym F # Funkcja:
let funAsLinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e
którym wydaje się, że powinno oznaczać dokładnie to samo, co FunAs.LinqExpression
, przekonasz się, że nie można nazwać w ten sam sposób. Na przykład, jeśli spróbujesz to:
let linqExpr = funAsLinqExpression(fun (e:MyEntity) -> e.Id = 42)
Dostaniesz (nieco nieprzydatne) Błąd: „Funkcja ta zajmuje zbyt wiele argumentów, lub jest używana w kontekście, którego funkcja nie jest expected`.
Dzięki temu, że ta funkcja jest elementem typu .NET, możemy skorzystać z pomocy F # "Wygląda na to, że wywołujesz API .NET, który oczekuje ekspresji w stylu LINQ, pozwól mi zająć się tym dla ciebie" cecha.
(Możliwe, że istnieje jakiś bardziej wyraźny sposób zadawania kompilator LINQ aby wykonać tę samą sztuczkę dla ciebie, nie przynosząc typ .NET na zdjęciu, ale nie znalazłem go.)
Hej, znajdujesz prostszy sposób na zrobienie tego? – nicolas
na stronie, jest tu powiązane pytanie (nie z cytatami) http://stackoverflow.com/questions/3392000/interop-between-f-and-c-sharp-lambdas – nicolas