mbraceproject / FsPickler

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

CustomPickler on class with an unpickleable base class #33

Closed iainnicol closed 9 years ago

iainnicol commented 9 years ago

I have a (derived) class I'd like to pickle. So I've implemented CustomPickler. However, my class derives from a dynamic class which FsPickler cannot pickle. My CustomPickler on the derived class doesn't ask FsPickler to pickle the unpickleable base class. However, FsPickler won't pickle my derived class.

Expressed in terms of a failing test case: https://github.com/iainnicol/FsPickler/commit/6d63baa99b9d6340a4ac1ee43c8f3288ba55bf47

IYHO, is this a valid use case?

Regards.

eiriktsarpalis commented 9 years ago

That's an interesting question. I believe that the current behaviour is correct. The type carrying the CustomPickler attribute may be serializable, but it is still a subtype of a nonserializable type. This means that instances of the former can be freely substituted in expressions of the latter. This may lead to unexpected results:

let pickle (t : 'T) = 
    let pickler = FsPickler.GeneratePickler<'T>()
    Json.pickle pickler t

let x = new ClassWithPicklerFactoryInheritsNonSerializable(42)

pickle x // successful
pickle (x :> NonSerializable) // exception

I think that the ideal solution in your case would be to avoid using inheritance but rather wrap the nonserializable value in a type that carries the CustomPickler attribute.

iainnicol commented 9 years ago

Ah, good example. It's not good to violate the Liskov substitution principle.

I'll use your suggestion. As you know, CustomPickler works if the type has-a nonserializable field.