Skip to content
10 changes: 10 additions & 0 deletions src/MongoDB.Bson/Serialization/BsonSerializerRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
{
Expand Down Expand Up @@ -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))
{
Expand Down Expand Up @@ -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))
Comment thread
papafe marked this conversation as resolved.
{
throw new ArgumentException($"A serializer for {BsonUtils.GetFriendlyTypeName(serializer.ValueType)} cannot be registered for type {BsonUtils.GetFriendlyTypeName(type)}.");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Comment thread
kyra-rk marked this conversation as resolved.
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<ArgumentException>();
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<ArgumentException>();
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<Person>), serializer));
exception.Should().BeNull();

subject.GetSerializer(typeof(List<Person>)).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<Person>), serializer);
result.Should().BeTrue();

subject.GetSerializer(typeof(List<Person>)).Should().BeSameAs(serializer);
}

[Fact]
public void TryRegisterSerializer_should_return_true_when_serializer_is_not_already_registered()
{
Expand Down Expand Up @@ -189,5 +237,19 @@ public void TryRegisterSerializer_should_throw_when_different_serializer_is_alre
exception.Should().BeOfType<BsonSerializationException>();
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<IEnumerable<Person>>
{
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, IEnumerable<Person> value)
=> throw new NotImplementedException();

public override IEnumerable<Person> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
=> throw new NotImplementedException();
}
}
}