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

Force any class to be serialized as a BSON class map and dictionary implementations to serialize keys as regular BSON elements #221

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

Conversation

mfidemraizer
Copy link

Force any class to be serialized as BSON class map

Because some requirements in my project, I had to create a base class derived by some domain objects which implement IDictionary<TKey, TValue>, but these domain objects are still POCOs and I want them to be serialized using regular BSON class map serializer.

When I ran some test I found some issue: my domain object wasn't getting an auto-assigned GUID. After clonning the driver source code, I debugged the code step by step and I found that my domain objects were serialized as collections rather than POCOs, because they inherit a base class which implements IDictionary<TKey, TValue> as I mentioned above.

Then, I thought, what about a way to configure that certain types must be serialized as class maps to solve my issue?, and I implemented a serialization provider ForceAsBsonClassMapSerializationProvider to fix my problem.

For example, this new provider may be used as follows:

public class SomeImpl : IDictionary<string, object> 
{
    // Imagine that I've implemented all IDictionary<string, object> members
}

BsonSerializer.RegisterSerializationProvider(new ForceAsBsonClassMapSerializationProvider(typeof(IDictionary<string, object>)));

It can be also registered a concrete type to be forced as a BSON class map:

BsonSerializer.RegisterSerializationProvider(new ForceAsBsonClassMapSerializationProvider(typeof(SomeImpl)));

Or also both:

// Order doesn't matter...
BsonSerializer.RegisterSerializationProvider(new ForceAsBsonClassMapSerializationProvider(typeof(IDictionary<string, object>), typeof(SomeImpl)));

BSON class maps of classes implementing IDictionary<string, object>

It might happen that a class representing a domain object or an entity may also implement IDictionary<TKey, TValue> interface. In my case, it has happened to let my domain objects be extensible but also contain regular properties.

For now, Mongo C# driver supports extra elements as a dictionary property, but what about the above feature of holding those extra elements as keys of an entity implementing IDictionary<string, object>?

In order to get this new feature working, I've modified BsonClassMapSerializer to detect if a document type is also IDictionary<string, object> itself, and serialize its key-value pairs as regular BSON elements. The so-called feature applies to both serialization and deserialization.

Final thoughts

Because I feel that other developers might encounter the same limitations and they might need to workaround them, what about including these features as part of the driver as is?

Thank you in advance and I'll look forward for your comments, suggestions...!

Force any class to be serialized as a BSON class map and, if they're
dictionary implementations, to serialize keys as regular BSON elements.
@mfidemraizer
Copy link
Author

It would be great to get news about my pull request, since this feature is a must in one of my professional projects.

I could implement outside the driver, but BsonClassMapSerializationProvider is an internal class and this means I should copy-paste BsonClassMapSerializationProvider code to avoid re-inventing the wheel... and since ForceAsBsonClassMapSerializationProvider (my contribution) is just a wrapper of BsonClassMapSerializationProvider, copy-pasting it can be a bad idea, since I want to stick with your code base...

In fact, there're many internal classes, even methods and properties... It seems like I would require a lot of effort to implement the same feature absolutely decoupled from driver's code base, while the feature as part of the whole code base requires these few modifications.

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.

3 participants