有没有关于如何扩展/添加新关键字到查询表达式的文档或示例?这甚至可能吗?
例如,我想添加一个领先/滞后运算符。
除了@pad 提到的 Rx 框架的查询构建器之外,还有来自 F# 团队的 Wonseok Chae 的演讲,内容是包含查询表达式的计算表达式。我不确定会议是否被录制,但是有非常详细的幻灯片,其中包含一个关于生成 .NET IL 代码的查询语法的很酷的示例。
标准 F# 查询构建器的源代码可能是了解支持哪些类型的操作以及如何使用属性注释它们的最佳资源。
where
子句演示了您可能需要的关键属性:
[<CustomOperation("where",MaintainsVariableSpace=true,AllowIntoPattern=true)>]
member Where :
: source:QuerySource<'T,'Q> *
[<ProjectionParameter>] predicate:('T -> bool) -> QuerySource<'T,'Q>
该CustomOperation
属性定义操作的名称。(非常重要的)参数MaintainsVariableSpace
允许您说操作返回与输入相同类型的值。在这种情况下,之前定义的变量在操作后仍然可用。例如:
query { for p in db.Products do
let name = p.ProductName
where (p.UnitPrice.Value > 100.0M)
select name }
在这里,变量p
和name
之后仍然可以访问,where
因为where
仅过滤输入,但不会转换列表中的值。
最后,ProjectionParameter
允许您说p.UnitValue > 100.0M
实际上应该将其转换为一个函数,该函数接受上下文(可用变量)并评估此表达式。如果您不指定此属性,则操作仅获取参数的值,如下所示:
query { for p in .. do
take 10 }
在这里,参数10
只是一个简单的表达式,不能使用p
.
该语言的非常酷的功能。刚刚实现了反向查询QuerySource。
简单的例子,但只是一个演示。
module QueryExtensions
type ExtendedQueryBuilder() =
inherit Linq.QueryBuilder()
/// Defines an operation 'reverse' that reverses the sequence
[<CustomOperation("reverse", MaintainsVariableSpace = true)>]
member __.Reverse (source : Linq.QuerySource<'T,System.Collections.IEnumerable>) =
let reversed = source.Source |> List.ofSeq |> List.rev
new Linq.QuerySource<'T,System.Collections.IEnumerable>(reversed)
let query = ExtendedQueryBuilder()
现在它被使用了。
let a = [1 .. 100]
let specialReverse =
query {
for i in a do
select i
reverse
}