如何在不丢失原始类型的情况下接收扩展接口的类型

时间:2017-08-15 21:50:11

标签: f#

我刚刚开始使用F#而且我的大脑已经破碎,试图弄清楚如何使用它的类型而不必采用OO类型的编程。

这是我的情况我基本上想要创建一个方法,我提供类型和Id,它返回给我数据库中的对象。

所以基本上这就是我到目前为止所做的。

let client = MongoClient()
let database = client.GetDatabase("testdb")

let lowerCase (str : string) = 
    str.ToLower()

let nameOf (classType: Type) = 
    classType.Name

let nameTypeOf<'a> = 
    nameOf typeof<'a>   

let getCollection<'a> =
    let collectionName = nameTypeOf<'a> |> lowerCase
    database.GetCollection<'a> collectionName

let dbSelect<'a> id = 
    let collection = getCollection<'a>
    collection.Find(fun(x) -> x.Id = id).First()

所以我的问题是使用dbSelect,显然它不能编译,因为x是通用的,基本上我想创建一个带有Id的接口,所有我的对象都与它接口。 我知道如何使用类和继承来实现它,但我避免在cop库之外使用实例化的类。如果有的话,最好的功能方法是什么。

这是我期待用

来称呼它
type IDbObject = 
    abstract Id: string

type Item = 
    {
        Id: string
        Name: string
    }
    interface IDbObject with
        member x.Id = x.Id

let item = 
    selectDb<Item> "5993592a35ce962b80da1e22"

任何帮助将不胜感激。 如果有人想指出我的代码有多糟糕,那么任何反馈都非常感激

1 个答案:

答案 0 :(得分:5)

我不认为这里的解决方案与您在C#中的解决方案有很大不同。您可以约束泛型类型以使用接口成员,获得大致类似的内容:

let getCollection<'a when 'a :> IDbObject> () =
   let collectionName = nameTypeOf<'a> |> lowerCase
   database.GetCollection<'a> collectionName

let dbSelect<'a when 'a :> IDbObject> id =
   let collection = getCollection<'a>()
   collection.Find(fun (x : 'a) -> x.Id = id).First()

dbSelect的类型应推断为string -> #IDbObject,并在呼叫站点强制为string -> 'a