Создайте выражение 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' ,

Этот вопрос: Выражение > из F# func, кажется, решает проблему напрямую, но решение использует Microsoft.FSharp.Linq.QuotationEvaluation, которую я не могу найти в F# 3.0 для WinRT.

Как мне повернуть <@ 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) 
Другие вопросы по тегам