我不知道这是不是一个模式,所以不知道从哪里开始寻找。我会尝试解释我想要的东西。
给定带有成员Bar和Baz的类型Foo
,我可以创建一个包装类型A<Foo>
,它返回一个模拟实例Foo,以便我可以编写A<Foo>.Bar ...
吗?目标是它可以在引文中使用,例如<@ A<Foo>.Bar > 1 @>
要清楚。如何实施A
?
答案 0 :(得分:4)
是的,这是一种模式。
如果您正在以某种方式分析Foo
的属性,请使用类型Expr<Foo -> 'a>
的代码引用,如下所示:
let q = <@ fun (foo: Foo) -> foo.Bar @>
如果从上下文中知道报价的类型,您可以省略类型注释: Foo
:
let q : Expr<Foo -> 'a> = <@ fun foo -> foo.Bar @>
许多库以这种方式使用引号,包括query
计算表达式和我最喜欢的一个Argu,一个用于解析命令行参数的库。
答案 1 :(得分:2)
有可能使用类型提供程序完全按照您的要求执行操作,但这可能会比它的价值更多。在你的情况下,我只会使用像Foq这样的模拟框架,或者如果用例很简单,只需使用对象表达式:
type Foo =
abstract member Bar: int
let mockFoo =
{new Foo with
member __.Bar = 1
}
这是一个与您正在寻找使用Foq的内容相近的例子:
open Foq
type A<'a when 'a: not struct> = Mock<'a>
type Foo =
abstract member Bar: int
<@ A<Foo>().Create().Bar > 1 @>
在这种情况下,Bar
将始终为0.如果您希望它为非零,则需要进行设置,如下所示:
<@ A<Foo>().Setup(fun f -> <@ f.Bar @>).Returns(2).Create().Bar > 1 @>