Skip to content

Serializing discriminated union failed while using non-generic classes #3

Description

@chnlkw

Problem

I get an error when serializing A in SimpleUnion

[<MessagePackObject>]
type SimpleUnion =
  | A
  | B of int
  | C of int64 * float32

let resolver = WithFSharpDefaultResolver() :> IFormatterResolver
MessagePackSerializer.NonGeneric.Serialize(A.GetType(), A, resolver) // failed

The exception is

Message: System.TypeLoadException : Type 
'MessagePack.FSharp.Formatters.MessagePack_Tests_DUTest\+SimpleUnion\+_AFormatter4' 
from assembly 'MessagePack.FSharp.DynamicUnionResolver, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
 is attempting to implement an inaccessible interface.

But it can serialize A correctly with SimpleUnion2 which inserts a unit field.

[<MessagePackObject>]
type SimpleUnion2 =
  | A2
  | AU2 of unit
  | B2 of int
  | C2 of int64 * float32

Here is my test case
source

module MessagePack.Tests.DUTest

open Xunit
open MessagePack

let convert_nongeneric (value: 'a) =
  let resolver = WithFSharpDefaultResolver() :> IFormatterResolver
  let t = value.GetType()
  let bin : byte[] = MessagePackSerializer.NonGeneric.Serialize(t, value :> obj, resolver)
  let actual :'a = MessagePackSerializer.NonGeneric.Deserialize(t, bin, resolver) :?> 'a
  Assert.Equal<'a>(value, actual)

[<MessagePackObject>]
type SimpleUnion =
  | A
  | B of int
  | C of int64 * float32

[<MessagePackObject>]
type SimpleUnion2 =
  | A2
  | AU2 of unit
  | B2 of int
  | C2 of int64 * float32

[<Fact>]
let sampleA () =
    convert_nongeneric A  // failed

[<Fact>]
let ``sampleA2`` () =
    convert_nongeneric A2  // success

[<Fact>]
let sampleAU () =
    convert_nongeneric <| AU2 ()
    
[<Fact>]
let sampleB () =
    convert_nongeneric (B 1)
    convert_nongeneric (B2 1)

[<Fact>]
let sampleC () =
    convert_nongeneric <| C(1L, 1.0f)
    convert_nongeneric <| C2(1L, 1.0f)

Motivation

I am trying to porting this extension to Akka.Serialization.MessagePack, which uses MessagePackSerializer.NonGeneric to serialize a object.
This serialize function needs a given type value, which is get from obj.GetType() in Akka implementation.
I use the serializaion here

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions