Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation for automatically registering sealed serializers in polymorphic modules #2201

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from

Conversation

pdvrieze
Copy link
Contributor

This is an implementation for #2199 and #1865. This implementation just modifies the subclass method in the builder. It does (internally) expose the registered children in SealedSerializer. It is not possible to trigger this behaviour from manually written serializers (instead of SealedSerializer).

This does also remove the prohibition of registering sealed classes, but note that it will register the children of the sealed class, but not the sealed parent itself. The code does allow for overlaps (by ignoring the registration in this case) to accommodate overlapping hierarchies (although this can be abused in some ways) - it does mean that sealed child serializers can be manually overridden by registering the sub-serializer before the sealed parent.

@pdvrieze pdvrieze changed the title Sealed modules Implementation for automatically registering sealed serializers in polymorphic modules Feb 20, 2023
@sandwwraith
Copy link
Member

Hi, thanks for the PR! Feature is indeed looks useful, although I'm a reluctant about changing the behavior of existing function (it didn't throw exception on sealed classes before, so it's not adding a completely new functionality). Have you though about other possibilities of doing this? Like adding new subclassesOf function. Also, this doesn't quite fix #1865 because IIRC there was explicit request of creating new SealedClassSerializer out of existing two. @Whathecode will such function solve your problems?

@pdvrieze
Copy link
Contributor Author

I'll update the pull request later when I have time. While this introduces "changed" behaviour the current (without this request) implementation is not actually valid.

As sealed classes (and interfaces) are abstract they don't actually make valid serializers in the polymorphic case.

For serialization the value with never be directly of the sealed type, for deserialization it will never create a sealed instance.

The only challenge with changing existing behaviour is when existing code does register the base for polymorphic serialization, this could have 2 consequences:

  • The children may already be registered, this will cause duplicate registration exceptions
  • If the children weren't registered they would now be, perhaps making certain code paths work accidentally.

As the current code doesn't (appear to) throw an exception in case sealed parent is registered it may be best to use a separate function name. I'll update this in the pull request.

@Whathecode
Copy link
Contributor

Whathecode commented Apr 29, 2023

@sandwwraith At a glance, no. #1865 is a different use case.

At runtime (this is a generic framework), I need to be able to create a serializer which can handle all subclasses of multiple sealed classes that extend from this common interface.

I don't have the types available at compile time, thus I can't register them in a serial module as you would 'normally' do.

My use case is a framework in which the app building on top of it links in additional types, through reflection, which extend from an interface defined in the framework. The framework then supports serializing aggregations of such extending classes.

I haven't looked at whether I could somehow create a SerializersModule with dynamically retrieved types through reflection, which perhaps is possible? I would then need to expose that module instead of a serializer to the caller. If that's possible, I guess this feature could be used to achieve something similar? But, I currently don't have time to look into this.

@pdvrieze
Copy link
Contributor Author

pdvrieze commented May 2, 2023

I've updated the pull request by a split out function (although the tests that were deleted - and no longer are did verify that passing a sealed type serializer should fail for subclass).
@Whathecode If you have the serializer dynamically then you could use that to register all children to the module. Of course this only works if the base sealed type is serializable and you are not pulling all kinds of class loader shenanigans (that are not transparent to the sealed serializer).

…aled children of a class for polymorphic serialization of a shared (non-sealed) type.
…avoid casting warnings). Use a map to allow faster lookup of serializers to class (to allow for overlapping hierarchies).
@pdvrieze
Copy link
Contributor Author

@Whathecode The thing this pull request does is support the case where there is a polymorphic base type P, a sealed base B : P and leaf types L1 : B, L2: B, L9: B, etc.. The pull request allows one to, rather than register all leafs (L1…L9) independently as polymorphic child of P, "register" the sealed parent as child of P and all the actually serializable leaves are then registered automatically as serializers for the base type P (the sealed parent is by definition abstract so not can not/should not be registered itself).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants