[CSHARP-1578] Subclass of BsonDocument is not getting serialized Created: 25/Feb/16 Updated: 05/Apr/19 Resolved: 04/Apr/16 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | Serialization |
| Affects Version/s: | 2.2.3 |
| Fix Version/s: | None |
| Type: | Task | Priority: | Minor - P4 |
| Reporter: | Rajesh Reddy | Assignee: | Robert Stam |
| Resolution: | Done | Votes: | 0 |
| Labels: | question | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Windows 7 64 bit with C# driver 2.2.3 and MongoDB 3.2.3 |
||
| Attachments: |
|
| Description |
|
I have created a subclass from BsonDocument as below public class MyClassDocument : BsonDocument } But, MyClassDocument class is not getting serialized while making calls to any of the API methods, Error Message: |
| Comments |
| Comment by Robert Stam [ 29/Feb/16 ] | ||||||||||||||||||||||||||||||||||||||||
|
We would actually recommend that you not subclass BsonDocument. Can you take some other approach? | ||||||||||||||||||||||||||||||||||||||||
| Comment by Rajesh Reddy [ 27/Feb/16 ] | ||||||||||||||||||||||||||||||||||||||||
|
Thanks for the update @Robert Stam | ||||||||||||||||||||||||||||||||||||||||
| Comment by Robert Stam [ 25/Feb/16 ] | ||||||||||||||||||||||||||||||||||||||||
|
I am able to reproduce this. We weren't really expecting anyone to subclass BsonDocument, and as you have found out, if you do that, serialization of your custom subclass does not work out of the box. I used this class to reproduce this:
To understand how MyBsonDocument was being serialized I added the following line of code at the beginning of my test program:
And using the debugger I found that the type of the serializer was an instance of an EnumerableInterfaceImplementerSerializer<MyBsonDocument, BsonElement>. The driver chose this serializer because MyBsonDocument implements IEnumerable<BsonElement> (it inherits it from BsonDocument), and we assume that the usual serialization of any class that implements IEnumerable<T> is as an array of T. So that's why you see your MyBsonDocument value serialized as an array. In this case T is BsonElement, and the driver then needs a serializer for BsonElement. We can see which one it chooses with this line of code:
And find that it has chosen a BsonClassMapSerializer. Unfortunately, BsonClassMapSerializer does not work with BsonElement, so the result is that the BsonElement get serialized as "{ }". If you really want to subclass BsonDocument what you will need to do is wire things up so that your MyBsonDocument values get serialized correctly. You can do that with the following adapter serializer which delegates most of the work to the existing BsonDocumentSerializer:
And then you have to tell the driver to use this serializer for instances of MyBsonDocument. The easiest way is to use the [BsonSerializer] attribute on the MyBsonDocument class:
Now the driver has been configured to correctly serialize instances of MyBsonDocument. The test I used was:
Which produced the following value for the json variable:
One final note: since instances of MyBsonDocument are now serialized exactly the same as a BsonDocument, there is no way during deserialization to tell the difference between a BsonDocument and a MyBsonDocument. So in the code sample above, the rehydrated variable contains an instance of MyBsonDocument, but the value of the "m" element is a regular BsonDocument. |