Skip to content

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

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

Closed
wants to merge 1 commit into 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...!

…ized as BSON class maps. In addition, if the class implements IDictionary<string, object>, the keys that don't correspond to a regular class property will be both serialized and deserialized as regular BSON elements/values.
@mfidemraizer
Copy link
Author

Sorry, I'll add a new pull request in a better way (using a feature branch in my repo).

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

Successfully merging this pull request may close these issues.

2 participants