Этот фрагмент кода воспроизводит проблему, с которой я столкнулся при работе с производственным кодом. Функция содержитProperty представляет функцию реального мира, которая фактически находится в библиотеке, так что я не могу сказать, что это за сигнатура.
Проблема в том, что я не могу понять, как создать функцию-обертку, которая может принять нормальную функцию в качестве аргумента, а затем передать ее в containsProperty. Я могу вызывать containsProperty напрямую с помощью функции в качестве лямбда-выражения, но я не могу вызывать ее с помощью функции из какого-то другого источника.
Функция addToGroup - лучшая из всех, что я придумал, и она использует цитаты. У этого подхода есть две проблемы, которые я пытаюсь выяснить. Во-первых, как мне избавиться от броска Func в цитате? Возможно, как-нибудь переместить его в addToGroup? Во-вторых, могу ли я опираться на это, чтобы просто передать функцию? Мне не удалось найти то, что не приводит ни к ошибке времени компиляции, ни к ошибке времени выполнения.
Функция addToGroup2 - это то, что я хотел бы сделать, но она не компилируется. Сообщение об ошибке: «Нет доступных конструкторов для типа 'Quotations.Expr <' a> '".
Почему я пытаюсь бороться с этим? Потому что, пока я не могу обработать переданную функцию как значение первого класса, я не могу создать дизайн, который мне нужен. Я хочу, чтобы эти функции пришли из коллекции записей.
Если вы вставите этот фрагмент в LINQPad или что-то еще, закомментируйте addToGroup2 и вызовы к нему, чтобы этот фрагмент компилировался и выполнялся.
open System
open System.ComponentModel
open System.ComponentModel.DataAnnotations // Reference to this assembly required.
type CfgSettings = {
mutable ConnectionString: string
mutable Port: int
}
and CfgSettingsMetadata() =
static member containsProperty<'TProperty>(propertyExpression: Linq.Expressions.Expression<Func<CfgSettings,'TProperty>>) =
Console.WriteLine "good!"
static member addToGroup f =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
static member addToGroup2 (f: CfgSettings -> 'TProperty) =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression (Quotations.Expr<Func<CfgSettings,'TProperty>>f)) |> ignore
static member BuildMetadata () =
CfgSettingsMetadata.containsProperty(fun x -> x.ConnectionString)
CfgSettingsMetadata.containsProperty(fun x -> x.Port)
CfgSettingsMetadata.addToGroup <@ Func<_,_>(fun x -> x.ConnectionString) @>
CfgSettingsMetadata.addToGroup <@ Func<_,_>(fun x -> x.Port) @>
CfgSettingsMetadata.addToGroup2 (fun x -> x.ConnectionString)
CfgSettingsMetadata.addToGroup2 (fun x -> x.Port)
CfgSettingsMetadata.BuildMetadata()
Оба ответа на вопрос Выражение > из F # func несколько помогло мне, но я пока не нашел решения.