Создайте выражение Linq из функции F# для передачи в C#
Я пытаюсь использовать базу данных Lex.Db в проекте F# в приложении WinRT 8.1.
Я следую этому уроку для C#. Я успешно добавил ссылку на Lex.Db в проект F#, а простые вызовы в учебнике переведены в F# и скомпилированы (например, let db = new DbInstance("demo")
).
Проблема заключается в следующем коде C#:
db.Map<Contact>().Key(i => i.Id)
-- Редактировать --
Чтобы спасти других от дальнейшего чтения, в F# 3.0 это почти не проблема. Смотрите комментарий kvb ниже. Решение:
db.Map<Contact>().Key(fun i => i.Id)
-- /Редактировать ---
Key
функция ожидает Expression<Func<Contact,'a>>
и я не могу построить это в F#.
Очень похожий вопрос возникает в разделе Как передать выражения LinQ из кода F# в код C#. Рекомендуемое решение - использовать LeafExpressionConverter.QuotationToLambdaExpression
,
Я попробовал это следующим образом:
type Contact() =
member val Id = 0 with get, set
member val FirstName = "" with get, set
let db = new DbInstance("Demo")
let idExpr = LeafExpressionConverter.QuotationToLambdaExpression
<@ fun (c : Contact) -> c.Id @>
db.Map<Contact>().Key(idExpr) |> ignore // <- Error
Это приводит к ошибке компилятора на idExpr
:
Несоответствие типов. Ожидая Expression<Func<Contact,'a>>
но учитывая Expression<(Contact -> int)>
, Тип 'Func<Contact,'a>'
не соответствует типу 'Contact -> int'
,
Этот вопрос: Выражение
Как мне повернуть <@ fun (c : Contact) -> c.Id @>
в Expression<Func<Contact,'a>>
?
1 ответ
Microsoft.FSharp.Linq.QuotationEvaluation
в PowerPack, но начиная с версии 3.0 функциональность, которую он предоставляет, доступна в Core через LeafExpressionConverter
, Вы можете использовать код в вопросе, который вы связали, но измените его на использование LeafExpressionConverter
для части перевода.
open System
open System.Linq.Expressions
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.RuntimeHelpers
let toLinq (expr : Expr<'a -> 'b>) =
let linq = LeafExpressionConverter.QuotationToExpression expr
let call = linq :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
Expression.Lambda<Func<'a, 'b>>(lambda.Body, lambda.Parameters)