[CSHARP-1907] Type discriminators don't work when collection document type is an interface Created: 02/Feb/17 Updated: 22/Jan/24 |
|
| Status: | Investigating |
| Project: | C# Driver |
| Component/s: | Serialization |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Peter Garafano (Inactive) | Assignee: | Robert Stam |
| Resolution: | Unresolved | Votes: | 1 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Description |
|
When the T of a collection is an interface, the type discriminators do not get added properly to a query. One of two things happens depending on how you query them
The _t for each document in the database is correctly serialized, this appears to only be an issue for reading. Reproduction script:
|
| Comments |
| Comment by James Kovacs [ 11/Mar/21 ] |
|
Investigating further, the root cause of the problem is actually more subtle. IFoo uses an ObjectDiscriminatorConvention because BsonSerializer.LookupDiscriminatorConvention line 390 forces the use of this convention for interfaces. However this method is called for Widget1, we fall through the else on line 396, which uses the HierarchicalDiscriminatorConvention by default. Thus if you access the collection via the interface, the discriminator is looked up using the ObjectDiscriminatorConvention - which uses _t: "ClassName, Assembly" - whereas if you access it through the class, the discriminator is looked up using the HierarchicalDiscriminatorConvention - which uses a discriminator of _t: "ClassName". The root cause of the problem is that we use two different conventions - which use different default discriminator formats - to find the discriminator. This inconsistency is what leads to the observed issue. We are discussing how best to resolve this issue and will update this ticket once we have a plan forward. |
| Comment by James Kovacs [ 05/Mar/21 ] |
|
I did some quick investigation. FilterDefinitionBuilder.OfType<T> is calling ObjectDiscriminatorConvention.GetDiscriminator(Type nominalType, Type actualType) which delegates to TypeNameDiscriminator.GetDiscriminator(actualType). It is this latter method that is appending the assembly name of the type if it is available. TypeNameDiscriminator.GetDiscriminator(actualType) is only called from two places: 1. ObjectDiscriminatorConvention.GetDiscriminator(Type nominalType, Type actualType) I do not believe that we append assembly names to type discriminators elsewhere. If that is true, we should be able to fix this bug by removing the assembly name lookup code from that method. |
| Comment by James Turner [ 30/Mar/18 ] |
|
Is there any movement on this issue? I'm encountering the second issue listed here with `_t` arguments appearing the full type name + assembly where the records in the DB are saved with just the type name. Happy to help with potential dev work required, just need some direction of where the issue likely is. I'm looking at the `OfTypeBinder` (both the "Pipeline" and "EmbeddedPipeline") but not sure if the issue is this high up or more comes down to BSON serialization of types? Is it that really this `OfType` checks should be using the current discriminator? |