Zaid-Ajaj / LiteDB.FSharp

Advanced F# Support for LiteDB, an embedded NoSql database for .NET with type-safe query expression through F# quotations
MIT License
181 stars 20 forks source link

Object expression #10

Closed humhei closed 6 years ago

humhei commented 6 years ago

Any ideas about this feature? See Tests.ObjectExpression for details

humhei commented 6 years ago

This will support follow syntax

///provider.fs
type IColor =
    abstract member Color : string 

type IBarcode =
    abstract member Barcode : string 

type ISize =
    abstract member Size : int

type IItem = 
    abstract member Id : int
    abstract member Name : string
    abstract member Art : string
    abstract member Number : int
[<CLIMutable>]    
type EOrder=
  { Id: int
    Items : IItem list
    OrderNumRange: string }   

///customer.fs 
type Item1 =
    inherit IItem
    inherit IBarcode

type Item2 = 
    inherit IItem
    inherit ISize
    inherit IColor
let item1 = 
    { new Item1 with 
        member this.Id = 0
        member this.Art = "art"
        member this.Name = "name"
        member this.Number = 1000
        member this.Barcode = "7254301" }
let item2 = 
    { new Item2 with 
        member this.Id = 0
        member this.Art = field
        member this.Name = "name"
        member this.Number = 1000
        member this.Color = "red" 
        member this.Size = 39}
let tp = item1.GetType()
FSharpJsonConverter.registerInheritedConverterType<IItem>(tp)            
let eorder = { Id = 1; Items = [item1];  OrderNumRange = "" }

let queryedEOrder =
    db 
    |> LiteRepository.insertItem eorder
    |> LiteRepository.query<EOrder> 
    |> LiteQueryable.first

match queryedEOrder.Items with 
| [item] -> 
    let t = item :? IBarcode
    match item with 
    | :? IBarcode as item1 -> 
        printfn "%A" item1.Barcode
        pass()
    | _ -> fail()    
| _ -> fail()    

the items in queryedEOrder is type of Item1 but not IItem

Zaid-Ajaj commented 6 years ago

Hello @humhei this is very interesting and useful! I need to look closely at the code, at first sight there are a couple of things,

Thanks a lot!

humhei commented 6 years ago
  • Can you rename "$itName" to something more descriptive like "$interfaceName" (if that is what it refers to)
  • Can you add a couple of examples to the Readme as well?

I will do it

  • inheritedConverterTypes doesn't have to be concurrent because registrations are done once at startup

Are concurrentDictionary has any disadvantage? I prefer not to fix it Because i love the syntax of AddOrUpdate and GetOrAdd

Zaid-Ajaj commented 6 years ago

Are concurrentDictionary has any disadvantage?

In practice no, it is ok to keep it :smile:

let me know when you finish, and I will merge/publish etc.

humhei commented 6 years ago

I wil fix it tomorrow. Now i have to go to sleep

Zaid-Ajaj commented 6 years ago

Sure buddy, good night!

humhei commented 6 years ago

@Zaid-Ajaj there are some limitations of fsharp(I think) that restraint this feature I will explain them in Readme(Just wait for a while) Please read it and tell me if we open a issue in fsharp suggestion?

Zaid-Ajaj commented 6 years ago

Limitation 1

Yes this is a limitation of F# that is does not have structural equality by default but is this a limitation for this feature?

Please read it and tell me if we open a issue in fsharp suggestion?

No need for a fsharp language feature just for this, it doesn't make sense in the first place to do structural equality on arbitrary interfaces

Limitation 2

That is not a limitation, the code is correct: the list is generated only once, whether you generate it inside the object expression or outside, it doesn't matter

Looking the decompiled C# from compiled IL isn't helpful as this is the result of many compiler optimizations

Can you please remove the details on decompiled C# from the readme? if this is an actual problem (I don't think that is the case) then open an issue

humhei commented 6 years ago

https://github.com/humhei/LiteDB.FSharp/tree/object-expression#the-best-way-i-found-to-solve-this-limitations-now

Why this way cannot be treated by fsharp as default

image The codes is verbose but corrently serialized and deserialized

Zaid-Ajaj commented 6 years ago

@humhei It is the same code, the list is generated once, no limitation of F# or anything

humhei commented 6 years ago

@Zaid-Ajaj
The anonymous type generated by fsharp is quite different Which we use to serialization and deserialization image image

humhei commented 6 years ago

@Zaid-Ajaj Let's merge it? This is a feature may only used for myself But also have no conflits to current repo So i move the docs to inner docs folder? Do you have other things propose to change?

humhei commented 6 years ago

Limitation 1 Yes this is a limitation of F# that is does not have structural equality by default but is this a limitation for this feature? Please read it and tell me if we open a issue in fsharp suggestion? No need for a fsharp language feature just for this, it doesn't make sense in the first place to do structural equality on arbitrary interfaces

Open a issue in fsharp suggestion may be the last strategy i would take It seems there already exists too much suggestions about interface and OO feature Before it i would compile fsharp source code myself try to fix it, If it's a actual problem, i will open a issue

Zaid-Ajaj commented 6 years ago

Yeah it is ok to add the feature here because it does not conflict with the main api, but in the future I would rather not add it unless many users ask for it (the same with LiteRepository module). So please, next time, let us open a discussion first on feature to decide whether or not to add it before you start working on it

humhei commented 6 years ago

@Zaid-Ajaj finally find the way worked for me Not using object expression(It's really a hard way to treat with anonymous type) But using normal type inherientance It worked well without any limitations

See Tests.typeinherited.fs for detail

Zaid-Ajaj commented 6 years ago

@humhei Nice! Why don't you send a PR then :wink: