是否有一种更简单的方法来隐式使用F#中的接口?

时间:2014-04-27 15:53:22

标签: interface f#

我正在使用F#接口,通过创建一个简单的数据访问类。

界面是:

type IUserAccess =
    abstract member GetUsers : (dbSchema.ServiceTypes.Users -> bool) -> dbSchema.ServiceTypes.Users seq 
    abstract member GetAllUsers : unit -> dbSchema.ServiceTypes.Users seq 

在课堂上,我用这种方式调用方法:

type UserAccess() = 
    let db = dbSchema.GetDataContext()
    interface IUserAccess with
        member this.GetUsers cond  =
            let query = query {
                for row in db.Users do
                select row } 
            query |> Seq.where cond

        member this.GetAllUsers () =
            (this:>IUserAccess).GetUsers (fun _ -> true)

我有点担心的是我调用GetAllUsers函数的方式,特别是部分(this:>IUserAccess)。调用在同一个接口中实现的方法的最简单方法是什么?

我能想到的一个简单选项是直接在GetUsers类中创建UserAccess()方法,然后从GetUsersGetAllUsers的接口实现中调用它,但是意味着实现了一个新的私有方法,我想避免。还有其他选择吗?

2 个答案:

答案 0 :(得分:8)

我认为@vcsjones的解决方案可能是最好的选择,如果你想避免直接在类中定义一个单独的方法。也就是说,声明一个单独的方法实际上并不那么难看。您可以使用let绑定(它自动编译为私有方法)使用本地定义,我认为它使代码看起来非常好:

type UserAccess() = 
    let db = dbSchema.GetDataContext()
    let getUsers cond = 
      let query = query {
          for row in db.Users do
          select row } 
      query |> Seq.where cond

    interface IUserAccess with
        member this.GetUsers cond  = getUsers cond
        member this.GetAllUsers () = getUsers (fun _ -> true)

我通常非常喜欢这种风格,因为它将所有私有实现与您定义公开公开API的定义部分分开。

答案 1 :(得分:6)

F#总是显式实现接口,因此您的选项与您所说的非常相似,但您可以通过引入let绑定来避免冗余转换:

type IUserAccess =
    interface
        abstract member GetUsers : (obj -> bool) -> unit
        abstract member GetAllUsers : unit -> unit
    end

type Foo() as self =
    let userAccess = self :> IUserAccess
    interface IUserAccess with
        member this.GetUsers(q : (obj -> bool)) : unit =
           ()
        member this.GetAllUsers() =
            userAccess.GetUsers(fun _ -> true)

我只是简化了你的界面和对象,所以我可以快速编译一些东西。