-
Type:
Bug
-
Resolution: Duplicate
-
Priority:
Unknown
-
None
-
Affects Version/s: 3.0.0
-
Component/s: None
-
None
-
None
-
Dotnet Drivers
-
None
-
None
-
None
-
None
-
None
-
None
Summary
BsonClassMapSerializer uses the discriminator convention registered in the class map and falls back to standard implementations regardless of discriminator conventions registered globally in the serializer registry.
Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).
Version 3.0
How to Reproduce
This is a sample XUnit test class to reproduce the issue.
_namespace MongoDbTests;
public class BaseClass;
public class SubClassThatNormallyLivesSomewhereElseButWeDontCare : BaseClass;
public class DiscriminatorConventionTests
{
public DiscriminatorConventionTests()
{
// This was sufficient previously
var convention = new ObjectDiscriminatorConvention("_type");
BsonSerializer.RegisterDiscriminatorConvention(
typeof(BaseClass),
convention);
// This is now needed as well for the BsonClassMapSerialzer to get the correct discriminator convention
BsonClassMap.TryRegisterClassMap<BaseClass>(
map =>
);
// But its still not sufficient, to make it work.
// We have to register the SAME convention for EVERY potential sub type, which makes no sense.
BsonClassMap.TryRegisterClassMap<SubClassThatNormallyLivesSomewhereElseButWeDontCare>(
map =>
{
map.AutoMap();
map.SetDiscriminatorConvention(convention);
});
}
[Fact]
public void DeserializeSubClassWorks()
{
// Fails with "Element '_type' does not match any field or property of class MongoDbTests.SubClassThatNormallyLivesSomewhereElseButWeDontCare."
// if the Convention is not registered for the sub type.
var mustBeSubClassInstance = BsonSerializer.Deserialize<BaseClass>(
BsonDocument.Parse($"{{ _type: '
' }}"));
mustBeSubClassInstance.Should()
.BeOfType<SubClassThatNormallyLivesSomewhereElseButWeDontCare>();
}
}_
Additional Background
After upgrading to the C# Driver 3.0 a lot of things changed regarding discriminator conventions that are not documented.
We also had problems using OfType which could be solved by implementing the IHierarchicalDiscriminatorConvention interface and using registering our convention in the class map.
For this particular problem here, imo the culprit is the line
__
if (discriminatorConvention == null) { discriminatorConvention = _hasRootClass ? StandardDiscriminatorConvention.Hierarchical : StandardDiscriminatorConvention.Scalar; _discriminatorConvention = discriminatorConvention; }
in the BsonClassMap.GetDiscriminatorConvention method which was
__
if (discriminatorConvention == null) { discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(_classType); _discriminatorConvention = discriminatorConvention; }
before.
Registering custom discriminator conventions for a base class is useless in this case because a class map is created for every type and sub type and having this we are forced to register the exact same discriminator convention in every sub type class map to make it work.
Usually in a complex environment classes are distributed across multiple modules, so at the place of the base class mapping where we register the discriminator convention we have no knowledge of every possible sub type, so we cannot use AddKnownType or things like that. But in fact we also don't care, because our discriminator convention is supposed to handle this.
If for a reason resolving the discriminator convention of a class map really should fall back to the standard implementations and not the registry, it maybe should only do so if there is no base class map, otherwise should call _baseClassMap.GetDiscriminatorConvention()?
- depends on
-
CSHARP-5349 v3.0 breaks registering discriminator convention on base type
-
- Closed
-
- duplicates
-
CSHARP-5349 v3.0 breaks registering discriminator convention on base type
-
- Closed
-