在F#中,如何在lambda表达式中强制转换接口?

时间:2020-06-01 21:50:53

标签: interface f#

我发现F#中的接口概念与C#显着不同。

The following code in F# works correctly:

type MyVisit = {
        lastname : string
        firstname : string
        birthdate : DateTime
        appointment_time : DateTime
        service_time : DateTime
        posting_time : DateTime
        chart_number : int
    }

module FsNetwork =
    let context = Wsdl1.GetBasicHttpBinding_IMedicalService()
    let GetScheduleAsync (tableDate : DateTime) =
        async {
            let! data = context.GetOfficeScheduleAsync(tableDate) |> Async.AwaitTask
            return data |> Seq.map(fun q -> {
                MyVisit.lastname = q.lastname
                firstname = q.firstname
                birthdate = q.birthdate
                appointmentTime = q.appointment_time
                tservice = q.service_time
                posting_time = q.posting_time
                chart_number = q.chart_number
                })                  
        }
       |> Async.StartAsTask

但是,在实现以下接口时

type IVisit = 
    abstract member lastname: string with get
    abstract member firstname: string with get
    abstract member mi: string with get
    abstract member birthdate: Nullable<DateTime> with get
    abstract member appointmentTime : System.Nullable<DateTime> with get
    abstract member tservice : System.Nullable<DateTime> with get
    abstract member postingTime : System.Nullable<DateTime> with get
    abstract member chartNumber : System.Nullable<int> with get

type Visit = 
    interface IVisit with 
        member this.lastname = "lastname"
        member this.firstname = "FirstName"
        member this.mi = "mi"
        member this.birthdate = Nullable(DateTime(2020, 1, 1))
        member this.appointmentTime = Nullable(DateTime(2020, 1, 1)) 
        member this.tservice = Nullable(DateTime(2020, 1, 1)) 
        member this.postingTime = Nullable(DateTime(2020, 1, 1)) 
        member this.chartNumber = Nullable(0)

lambda现在失败 类型“访问”未定义字段,构造函数或成员“姓氏”

module FsNetwork =
    let context = Wsdl1.GetBasicHttpBinding_IMedicalService()
    let GetScheduleAsync (tableDate : DateTime) =
        async {
            let! data = context.GetOfficeScheduleAsync(tableDate) |> Async.AwaitTask
            return data |> Seq.map(fun q -> {
                Visit.lastname = q.lastname
                firstname = q.firstname
                birthdate = q.birthdate
                appointmentTime = q.appointment_time
                tservice = q.service_time
                posting_time = q.posting_time
                chart_number = q.chart_number
                })                  
        }
       |> Async.StartAsTask

尝试使用Visit:> IVisit.lastname = ...或Visit:#IVisit.lastname = ...强制转换为“ Visit”也失败。我敢肯定这很简单,这是怎么做的?

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

第二个代码段中使用的语法是记录初始化的代码段。但是,您想创建一个接口实例。

您可以通过创建一个类来做到这一点-但您的类定义还不十分完善,因为它没有构造函数。因此,您将需要一些基本的东西:

type Visit(first:string, last:string) = 
  interface IVisit with
    member x.first = first
    member x.last = last

这变得非常麻烦,因此我将改用另一个F#功能,即匿名对象表达式,它使您可以创建没有类的接口实例:

 { new IVisit with 
    member x.first = "Yadda"
    member x.last = "Yadda" }

使用此代码,您的代码应类似于:

let context = Wsdl1.GetBasicHttpBinding_IMedicalService()
let GetScheduleAsync (tableDate : DateTime) =
    async {
        let data = context.GetOfficeScheduleAsync(tableDate) |> Async.AwaitTask
        return data |> Seq.map(fun q -> 
          { new IVisit with 
            member this.mi = "??"
            member this.lastname = q.lastname
            member this.firstname = q.firstname
            member this.birthdate = q.birthdate
            member this.appointmentTime = q.appointment_time
            member this.tservice = q.service_time
            member this.postingTime = q.posting_time
            member this.chartNumber = q.chart_number })                  
    }
   |> Async.StartAsTask

也就是说,我真的不明白为什么在这里需要一个接口,而不是普通的F#记录。即使您要使用C#中的该库,一条记录也将看起来像普通的类。