mbraceproject / FsPickler

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

Exception whilst trying to pickle a DirectoryInfo in a .NET Framework application #105

Open JackMatusiewicz opened 6 years ago

JackMatusiewicz commented 6 years ago

Description


Trying to serialise a DirectoryInfo succeeds in a .NET Core app but fails in a .NET Framework app

Code


open MBrace.FsPickler
open MBrace.FsPickler.Json
open System.IO

let makeDirectoryInfoPickler (resolver : IPicklerResolver) =
    let stringPickler = resolver.Resolve<string> ()

    let read (r : ReadState) =
        stringPickler.Read r "DirectoryInfo" |> DirectoryInfo

    let write (w : WriteState) (d : DirectoryInfo) =
        stringPickler.Write w "DirectoryInfo" d.FullName

    Pickler.FromPrimitives (read,write)

[<EntryPoint>]
let main _ =
    let di = DirectoryInfo "test"

    let registry = CustomPicklerRegistry ()
    registry.RegisterFactory makeDirectoryInfoPickler
    let cache = PicklerCache.FromCustomPicklerRegistry registry
    let jser = FsPickler.CreateJsonSerializer(picklerResolver = cache)
    di |> jser.PickleToString |> printfn "%s"
    0

Expected behavior


Identical behaviour between .NET Core and .NET Framework, ideally with it working in both.

Actual behavior


Crashes in .NET framework with the following stack trace:

MBrace.FsPickler.NonSerializableTypeException
  HResult=0x80131500
  Message=Type 'System.IO.DirectoryInfo' is not serializable.
  Source=FSharp.Core
  StackTrace:
   at Microsoft.FSharp.Core.Operators.Raise[T](Exception exn)
   at MBrace.FsPickler.PicklerCache.GeneratePickler[T]() in C:\Users\source\repos\FsPicklerTest\FsPicklerTest\FsPickler-5.2\src\FsPickler\PicklerGeneration\PicklerCache.fs:line 64
   at MBrace.FsPickler.FsPicklerTextSerializer.Serialize[T](TextWriter writer, T value, FSharpOption`1 pickler, FSharpOption`1 streamingContext, FSharpOption`1 leaveOpen) in C:\Users\source\repos\FsPicklerTest\FsPicklerTest\FsPickler-5.2\src\FsPickler\FsPickler\TextSerializer.fs:line 35
   at <StartupCode$FsPickler>.$TextSerializer.PickleToString@122.Invoke(TextWriter m, T v) in C:\source\repos\FsPicklerTest\FsPicklerTest\FsPickler-5.2\src\FsPickler\FsPickler\TextSerializer.fs:line 122
   at MBrace.FsPickler.FsPicklerTextSerializer.PickleToString[T](T value, FSharpOption`1 pickler, FSharpOption`1 streamingContext)
   at Program.main(String[] _arg1) in Program.fs:line 27

Current Findings


I did some investigating into this, it seems the cause is that 'isUnsupportedType' inside PicklerGenerator.fs checks the type to see if IsMarshalByRef is set. In the .NET framework app it is set to true. However, in .NET Core it is not.

Related information

Operating system - Windows 10 Target F# runtime 4.4.3.0 (4.1) .NET Framework 4.7.1 .NET Core 2.0 FsPickler 5.2.0 FsPickler.Json 5.2.0

komadori commented 6 years ago

Hi @eiriktsarpalis,

It looks like this issue should be fixed now that you've merged PR #106 . Do you have any idea how long it will be before an FsPickler release will include this change?

Thanks, Robin.