[CSHARP-485] Investigate Interface Usage in Bson library Created: 04/Jun/12 Updated: 08/Apr/15 Resolved: 08/Apr/15 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | None |
| Affects Version/s: | 1.4.2 |
| Fix Version/s: | 2.0 |
| Type: | Improvement | Priority: | Minor - P4 |
| Reporter: | Craig Wilson | Assignee: | Robert Stam |
| Resolution: | Done | Votes: | 6 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Description |
|
BsonClassMap.RegisterClassMap<IInterface> will not work correctly, even though there might be some validity to the need. Let's investigate this as well as other aspects of using interfaces as domain entities. [Edit 2015-04-08] Instead of calling BsonClassMap.RegisterClassMap<IInterface>, what is actually needed is to call BsonSerializer.RegisterSerializer<IInterface>(...). See comment below created on 2015-04-08. |
| Comments |
| Comment by Robert Stam [ 08/Apr/15 ] | ||||||||||||||||||||||||||||||
|
In the 2.0 version of the driver the sample types provided by Gustavo Gondim can be successfully serialized and deserialized. If you simply let the driver serialize them using default settings, the document that gets stored looks like this:
The "_t" values are called discriminators, and are required because we can't instantiate instances of an interface. We need to select a concrete class to instantiate. The "_t" value tells us which concrete class to instantiate. If you want to suppress the "_t" values and use some implied concrete class during deserialization, you can configure that. To configure that in code, do this:
This tells the driver that whenever it needs to deserialize an IPartner, it should assume that the implied implementation of the IPartner interface that we want to use is the Partner class (and similarly for Phone). To configure this using attributes, define your classes as:
Where we are using the [BsonSerializer] attribute to accomplish the same thing. Unless you have a specific reason for needing to suppress the "_t" values, by far the easiest course of action is to simply let the driver write out the "_t" values and then everything just works automatically. | ||||||||||||||||||||||||||||||
| Comment by Robert Stam [ 19/Aug/14 ] | ||||||||||||||||||||||||||||||
|
While it might be possible to get a class map for an interface to work when serializing objects, it's not likely to work on the way back in because we can't instantiate an instance of an interface, we need to instantiate an instance of a concrete class. So it seems like the interface instance should be serialized as the actual type (the concrete type) with a discriminator (usually _t) to identify the actual type. | ||||||||||||||||||||||||||||||
| Comment by Gustavo Gondim [ 28/Jan/13 ] | ||||||||||||||||||||||||||||||
|
It will be perfect if this improvement will be done. There is a real example with interface deserialization in C# Driver:
Where "User" is the document to be stored in database. To not see the MongoDB.Bson.BsonSerializationException today, when casting from a derived type to an interface, it needs to implement the BsonClassMap.RegisterClassMap with a cast to the interface. In another way, it needs to implement a custom BSON serializer class. This improvement may reduce a lot of work. |