mbraceproject / FsPickler

A fast multi-format message serializer for .NET
http://mbraceproject.github.io/FsPickler/
MIT License
325 stars 52 forks source link

Serialize and Deserealize anonimus records in Expressions #113

Closed Neftedollar closed 5 years ago

Neftedollar commented 5 years ago

Hey! I'm trying to send expression from one process to another. Expression is:

<@ fun (s:string) ->
        let rcrd = {| FstStr = s |}
        rcrd.FstStr
        @>

And as tree

Let (rcrd, NewRecord (<>f__AnonymousType1712465342`1', s),
     PropertyGet (Some (rcrd), FstStr, []))

While I trying to deserialize it (another process) I'm getting error

MBrace.FsPickler.FsPicklerException: Error deserializing object of type 'Microsoft.FSharp.Quotations.FSharpExpr'. ---> System.IO.FileNotFoundException: Could not load file or assembly ...

It's ok. Deserializer trying to find type <>f__AnonymousType17124653421'` But maybe deserilizer can understand that it is an anonimus type and maybe it can create another one with same structure?

Neftedollar commented 5 years ago

For example like tuples:

<@ fun (s:string) ->
        let rcrd = (s,"tsda")
        let (a,b) = rcrd
        a   @>

tree

Let (rcrd, NewTuple (s, Value ("tsda")),
     Let (b, TupleGet (rcrd, 1), Let (a, TupleGet (rcrd, 0), a)))
eiriktsarpalis commented 5 years ago

Does it work when deserializing on the same process?

Neftedollar commented 5 years ago

@eiriktsarpalis checking

Neftedollar commented 5 years ago

@eiriktsarpalis

  let ex = <@ fun (s:string) -> 
        let rcrd = {| Fst = s |} 

        rcrd.Fst @>
  printfn "ex %A" ex

  let bs = FsPickler.CreateBinarySerializer()
  let bts = bs.Pickle ex
  let exp = bs.UnPickle<Quotations.Expr<string -> string>>(bts)
  printfn "exp unpickled: %A" exp
  let f =  exp.Compile()
  let result = f "LALA"
  printfn "result - %s" result

produce this:

ex Lambda (s,
        Let (rcrd, NewRecord (<>f__AnonymousType1872059638`1', s),
             PropertyGet (Some (rcrd), Fst, [])))
exp unpickled: Lambda (s,
        Let (rcrd, NewRecord (<>f__AnonymousType1872059638`1', s),
             PropertyGet (Some (rcrd), Fst, [])))
result - LALA

So it's working

Neftedollar commented 5 years ago

I see https://github.com/eiriktsarpalis/TypeShape/commit/cbc42a91cad1226d8acfc2818f3592aacd2e7e34 Can I help with something?

eiriktsarpalis commented 5 years ago

This is expected behaviour. Anonymous records are still nominal types in disguise, each assembly generates its own definitions. So you can't really deserialize an anonymous record without having the related assembly available, much like normal records.

I'm going to close this issue.

Neftedollar commented 5 years ago

ok. Thank you!