I need a function to convert types from a third-party library to IDictionarys so they can be easily serialized (to JSON). There are dependencies between the types so the dictionaries are sometimes nested.
Right now I have something hideous like this:
//Example type
type A(name) =
member __.Name = name
//Example type
type B(name, alist) =
member __.Name = name
member __.AList : A list = alist
let rec ToSerializable x =
match box x with
| :? A as a -> dict ["Name", box a.Name]
| :? B as b -> dict ["Name", box b.Name; "AList", box (List.map ToSerializable b.AList)]
| _ -> failwith "wrong type"
This would convert everything to a primitive type, an IEnumerable of such a type, or a dictionary.
This function will keep growing as types are added (ugh). It’s not type-safe (requiring the catch-all pattern). Figuring out which types are supported requires perusing the monolithic pattern match.
I’d love to be able to do this:
type ThirdPartyType with
member x.ToSerializable() = ...
let inline toSerializable x =
(^T : (member ToSerializable : unit -> IDictionary<string,obj>) x)
let x = ThirdPartyType() |> toSerializable //type extensions don't satisfy static member constraints
So, I’m looking for creativity here. Is there a better way to write this that addresses my complaints?
Here’s one possible solution that addresses the type-safety question, though not necessarily your extensibility question: