最近有一个类似的问题,在类型声明中使用了成员约束。
我不确定如何更正您的示例以使其编译,但如果这是不可能的,我不会感到惊讶。成员约束旨在与静态解析的类型参数一起使用,尤其是与inline
函数或成员一起使用,我认为将它们与类的类型参数一起使用不是惯用的 F# 代码。
我认为您的示例更惯用的解决方案是定义一个接口:
type INamed =
abstract Name : string
type ListEntryViewModel<'T when 'T :> INamed>(model:'T) =
member this.Name = model.Name
(实际上,ListEntryViewModel
可能不需要类型参数,可以直接INamed
作为构造函数参数,但这样写可能会有一些好处。)
现在,您仍然可以使用鸭子类型并ListEntryViewModel
在具有属性的事物上使用Name
,但不要实现INamed
接口!这可以通过编写一个inline
返回INamed
并使用静态成员约束来捕获现有Name
属性的函数来完成:
let inline namedModel< ^T when ^T : (member Name : string)> (model:^T)=
{ new INamed with
member x.Name =
(^T : (member Name : string) model) }
然后,您可以通过编写不需要实现接口而只需要属性的ListEntryViewModel(namedModel someObj)
位置来创建视图模型。someObj
Name
我更喜欢这种风格,因为通过使用接口,您可以更好地记录您对模型的要求。如果您有其他不符合该方案的对象,您可以调整它们,但如果您正在编写模型,那么实现接口是确保它公开所有必需功能的好方法。