【发布时间】:2018-05-06 06:19:35
【问题描述】:
此代码 sn-p 重现了我在使用某些生产代码时遇到的问题。函数 containsProperty 表示一个实际存在于库中的真实世界函数,因此我对签名是什么没有发言权。
问题是我不知道如何创建一个可以将普通函数作为参数的包装函数,然后将其传递给 containsProperty。我可以直接使用函数作为 lambda 表达式调用 containsProperty,但我不能使用来自其他来源的函数调用它。
addToGroup 函数是迄今为止我想出的最好的函数,它使用引号。这种方法有两个问题,我正在努力解决。首先,我如何摆脱引用中的 Func 演员?也许以某种方式将它移到 addToGroup 中?其次,我可以以此为基础来传递一个函数吗?我没有成功找到不会产生编译时错误或运行时错误的东西。
函数 addToGroup2 是我想做的,但它不能编译。错误消息是“没有可用于类型 'Quotations.Expr' 的构造函数”。
我为什么要为此烦恼?因为只要我不能将传入的函数视为一流的值,我就无法创建我所追求的设计。我希望这些函数来自记录集合。
如果您将此 sn-p 粘贴到 LINQPad 或其他东西中,请注释掉 addToGroup2 及其对它的调用,以使 sn-p 编译和运行。
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()
Expression<Func<T, bool>> from a F# func 的两个答案都对我有所帮助,但我还没有找到解决方案。
【问题讨论】:
标签: f#