diff --git a/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs b/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs index 429386f6019..586232c662f 100644 --- a/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs +++ b/src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs @@ -94,6 +94,7 @@ public void RegisterSerializer(Type type, IBsonSerializer serializer) throw new ArgumentNullException("serializer"); } EnsureRegisteringASerializerForThisTypeIsAllowed(type); + EnsureSerializerIsCompatibleWithType(serializer, type); if (!_cache.TryAdd(type, serializer)) { @@ -134,6 +135,7 @@ public bool TryRegisterSerializer(Type type, IBsonSerializer serializer) throw new ArgumentNullException(nameof(serializer)); } EnsureRegisteringASerializerForThisTypeIsAllowed(type); + EnsureSerializerIsCompatibleWithType(serializer, type); if (_cache.TryAdd(type, serializer)) { @@ -192,5 +194,13 @@ private void EnsureRegisteringASerializerForThisTypeIsAllowed(Type type) throw new ArgumentException(message, "type"); } } + + private void EnsureSerializerIsCompatibleWithType(IBsonSerializer serializer, Type type) + { + if (!serializer.ValueType.IsAssignableFrom(type)) + { + throw new ArgumentException($"A serializer for {BsonUtils.GetFriendlyTypeName(serializer.ValueType)} cannot be registered for type {BsonUtils.GetFriendlyTypeName(type)}."); + } + } } } diff --git a/tests/MongoDB.Bson.Tests/Serialization/BsonSerializerRegistryTests.cs b/tests/MongoDB.Bson.Tests/Serialization/BsonSerializerRegistryTests.cs index 6989565923c..1f97d42994c 100644 --- a/tests/MongoDB.Bson.Tests/Serialization/BsonSerializerRegistryTests.cs +++ b/tests/MongoDB.Bson.Tests/Serialization/BsonSerializerRegistryTests.cs @@ -97,6 +97,54 @@ public void RegisterSerializer_should_throw_when_serializer_is_already_registere exception.Message.Should().Contain("There is already a serializer registered for type Object"); } + [Fact] + public void RegisterSerializer_should_throw_when_type_and_serializer_do_not_match() + { + var subject = new BsonSerializerRegistry(); + var intSerializer = new Int32Serializer(); + + var exception = Record.Exception(() => subject.RegisterSerializer(typeof(long), intSerializer)); + + exception.Should().BeOfType(); + exception.Message.Should().Be("A serializer for Int32 cannot be registered for type Int64."); + } + + [Fact] + public void TryRegisterSerializer_should_throw_when_type_and_serializer_do_not_match() + { + var subject = new BsonSerializerRegistry(); + var intSerializer = new Int32Serializer(); + + var tryException = Record.Exception(() => subject.TryRegisterSerializer(typeof(long), intSerializer)); + + tryException.Should().BeOfType(); + tryException.Message.Should().Be("A serializer for Int32 cannot be registered for type Int64."); + } + + [Fact] + public void RegisterSerializer_should_allow_serializer_for_base_type() + { + var subject = new BsonSerializerRegistry(); + var serializer = new PeopleSerializer(); + + var exception = Record.Exception(() => subject.RegisterSerializer(typeof(List), serializer)); + exception.Should().BeNull(); + + subject.GetSerializer(typeof(List)).Should().BeSameAs(serializer); + } + + [Fact] + public void TryRegisterSerializer_should_allow_serializer_for_base_type() + { + var subject = new BsonSerializerRegistry(); + var serializer = new PeopleSerializer(); + + var result = subject.TryRegisterSerializer(typeof(List), serializer); + result.Should().BeTrue(); + + subject.GetSerializer(typeof(List)).Should().BeSameAs(serializer); + } + [Fact] public void TryRegisterSerializer_should_return_true_when_serializer_is_not_already_registered() { @@ -189,5 +237,19 @@ public void TryRegisterSerializer_should_throw_when_different_serializer_is_alre exception.Should().BeOfType(); exception.Message.Should().Contain("There is already a different serializer registered for type Object"); } + + private class Person + { + public string Name { get; set; } + } + + private class PeopleSerializer : SerializerBase> + { + public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, IEnumerable value) + => throw new NotImplementedException(); + + public override IEnumerable Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + => throw new NotImplementedException(); + } } }