2014-04-27 16 views
7

Gram trochę z interfejsami F #, tworząc prostą klasę dostępu do danych.Czy istnieje prostszy sposób niejawnego używania interfejsów w języku F #?

Interfejs jest:

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

W klasie, jestem wywołanie metody w ten sposób:

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) 

Co ja jestem zaniepokojony z bit jest sposób wzywam GetAllUsers funkcja, w szczególności z częścią (this:>IUserAccess). Jaki jest najprostszy sposób wywoływania metod zaimplementowanych w tym samym interfejsie?

Jedna prosta opcja mogę myśleć jest tworzenie GetUsers metody bezpośrednio w UserAccess() klasy, a następnie wywołanie go z implementacji interfejsu zarówno GetUsers i GetAllUsers, ale to oznacza nową metodę prywatną wdrożone, który chciałbym uniknąć. Czy istnieje inna opcja?

Odpowiedz

6

F # zawsze implementuje interfejsy wyraźnie, więc opcje są dość dużo, jak wspomniano, ale można uniknąć redundantny odlewania poprzez wprowadzenie let Oprawa:

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) 

Właśnie uproszczony interfejs i sprzeciw, więc mogłem dostać coś naprawdę szybko się kompiluje.

+0

Dzięki, to jest właśnie proste ulepszenie, którego szukałem! –

7

Myślę, że rozwiązanie @vcsjones jest prawdopodobnie najlepszą opcją, jeśli chcesz uniknąć zdefiniowania osobnej metody bezpośrednio w klasie. To powiedziawszy, deklarowanie oddzielnej metody nie jest wcale tak brzydkie. Można użyć lokalną definicję używając let wiązania (który jest automatycznie zestawiane jako prywatny metody) i myślę, że to sprawia, że ​​kod wyglądać całkiem ładnie:

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) 

ja generalnie całkiem jak tego stylu, ponieważ oddziela cały prywatny realizację z części definicji, w której definiujesz publiczny interfejs API.

Powiązane problemy