mbraceproject / FsPickler

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

Extending 3rd party lib custom picklers #40

Closed haraldsteinlechner closed 9 years ago

haraldsteinlechner commented 9 years ago

I vaguely remember a possibility to resolve custom picklers externally, i.e. it was possible to define picklers for an existing type outside of the type/library. Unfortunately this seems to be gone [1] :(

One solution at user level would be to allow extension methods to be considered for pickler resolving: Lib 1: type Test = Test of () Lib 2:

[<CustomPickler>]
type Test with
    static member resolve (p : IPicklerResolver) : Pickler<Urdar> =`....

The solution would be neat but of course possibly impossible to implement due to the compilation technique of extensions in F#.

What is the recommended way to accomplish this type of extensibility?

[1] https://github.com/nessos/FsPickler/issues/26

eiriktsarpalis commented 9 years ago

You are right, it's difficult and often ambiguous to extract picklers from extension method definitions.

The current best way of using custom picklers is to pass them parametrically to the serialization/deserialization method. For instance:

open Nessos.FsPickler.Combinators

let binary = FsPickler.CreateBinary()
let pickler : Pickler<int * string> = Pickler.pair Pickler.int Pickler.string

binary.Serialize(stream, pickler, (42,"42"))
haraldsteinlechner commented 9 years ago

well this explicit creation does not work with auto generated picklers. I'm kind of happy with "don't care auto pickler generation" but i just want to override default behaviour for some types...

eiriktsarpalis commented 9 years ago

I understand. In the end I had this feature removed because of state-related bugs and because it was awkward to register custom picklers for generic types.

haraldsteinlechner commented 9 years ago

do you have any ideas how to bring the feature back in a clean way? this state right now makes the library kind of unusable for my purposes. I see, there is a genericity problem but can't we just register a generic function an instantiate those with actual generic arguments during serialization? If the user needs constraints on those types he is free to add them - at runtime specialization either works or not... if not, the provided pickler generator is ignored and resolving continues just like before.

eiriktsarpalis commented 9 years ago

Not without significant refactoring of the library, and with a solution that is awkward, ambiguous and partial. It also introduces a class of bugs that can easily appear by misuse of the API.

I dug up the old code that implemented this feature. I hope it will help convince you that this is not a desirable feature given the design of the library: Pickler factory APIs Generation Implementation

eiriktsarpalis commented 9 years ago

This has been partially addressed as of 1.2.5, closing for now.