[CSHARP-3494] Discriminator conventions don't work properly with generic types Created: 19/Mar/21  Updated: 20/Jan/23

Status: Backlog
Project: C# Driver
Component/s: API, BSON, Serialization
Affects Version/s: 2.12.0
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Raphael Rabl Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: Serialization, generics
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

TargetFramework: .NET 5
OS: Windows 10
MongoDB: Community Edition 4.4.3 2008R2Plus SLL (64 bit) - installed as Windows Service


Issue Links:
Depends
is depended on by CSHARP-3989 oDATA $select support with LINQ3 Closed
Duplicate
is duplicated by CSHARP-1240 Type name store in the _t field missi... Closed
Problem/Incident
causes CSHARP-1240 Type name store in the _t field missi... Closed
Epic Link: Improve Serialization

 Description   

The default discriminator conventions (ie. HierarchicalDiscriminatorConvention) don't work properly with generic types. Trying to find/insert documents with varying generic types will cause an exception "Ambiguous discriminator 'Type`1'.".

The problem and solution is also explained in this stackoverflow post: https://stackoverflow.com/questions/25891373/mongodb-c-sharp-driver-type-discriminators-with-generic-class-inheriting-from-no

The problem seems to be, that the default discriminator conventions use the type's Name property instead of its FullName or AssemblyQualifiedName property.
For some reason, using FullName will throw an exception: "Unknown discriminator value ...', while AssemblyQualifiedName works.

This is also what causes this older issue: https://jira.mongodb.org/browse/CSHARP-1240

The fix for my application was creating a custom discriminator convention that inherits from HierarchicalDiscriminatorConvention and return:

classMap.ClassType.AssemblyQualifiedName

instead of:

classMap.Discriminator

inside of the GetDiscriminator method.
see: https://github.com/mongodb/mongo-csharp-driver/blob/v2.12.x/src/MongoDB.Bson/Serialization/Conventions/HierarchicalDiscriminatorConvention.cs

Solution/suggestion:

The problem seems to be, that inside of BsonClassMap.cs, the _discriminator field is assigned a wrong value:

_discriminator = _classType.Name;

see: https://github.com/mongodb/mongo-csharp-driver/blob/v2.12.x/src/MongoDB.Bson/Serialization/BsonClassMap.cs#L973

Because of the usage of _classType.Name, the discriminator conventions won't work for generic types.

A quick fix could be to instead assign AssemblyQualifiedName:

_discriminator = _classType.AssemblyQualifiedName;

in turn, the default discriminator conventions that access

classMap.Discriminator

will now receive the correct name.

I'm not sure why FullName does not work, it should be investigated whether it is better to use it over AssemblyQualifiedName.



 Comments   
Comment by James Kovacs [ 26/Mar/21 ]

Hi, Raphael,

Thank you for reporting this issue. You are correct that it is related to CSHARP-1240. The same concerns apply that although the current behaviour is problematic, however we fix it will result in a backward breaking change. We have scheduled an analysis of potential serialization improvements in an upcoming sprint and I have flagged this ticket to be part of that analysis. Thank you in advance for your patience and we will update this ticket when we decide on a path forward for this and related issues.

Sincerely,
James

Generated at Wed Feb 07 21:45:26 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.