From ec4f48e4255588ab22d7e49246566c89f7f2cb35 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 12 Dec 2024 09:54:17 -0500
Subject: [PATCH 01/19] rebase 1
---
.../EnumRepresentationConvention.cs | 50 +++++++++----------
.../EnumRepresentationConventionTests.cs | 33 ++++++++++++
2 files changed, 58 insertions(+), 25 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index 55ad9a00b9e..f9c33973a28 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -15,6 +15,7 @@
using System;
using System.Reflection;
+using MongoDB.Bson.Serialization.Serializers;
namespace MongoDB.Bson.Serialization.Conventions
{
@@ -49,38 +50,37 @@ public EnumRepresentationConvention(BsonType representation)
/// The member map.
public void Apply(BsonMemberMap memberMap)
{
- var memberType = memberMap.MemberType;
- var memberTypeInfo = memberType.GetTypeInfo();
+ var serializer = memberMap.GetSerializer();
- if (memberTypeInfo.IsEnum)
+ if (memberMap.MemberType.IsEnum && serializer is IRepresentationConfigurable representationConfigurableSerializer)
{
- var serializer = memberMap.GetSerializer();
- var representationConfigurableSerializer = serializer as IRepresentationConfigurable;
- if (representationConfigurableSerializer != null)
- {
- var reconfiguredSerializer = representationConfigurableSerializer.WithRepresentation(_representation);
- memberMap.SetSerializer(reconfiguredSerializer);
- }
+ memberMap.SetSerializer(representationConfigurableSerializer.WithRepresentation(_representation));
return;
}
- if (IsNullableEnum(memberType))
+ var reconfiguredSerializer = Reconfigure(serializer);
+ if (reconfiguredSerializer is not null)
{
- var serializer = memberMap.GetSerializer();
- var childSerializerConfigurableSerializer = serializer as IChildSerializerConfigurable;
- if (childSerializerConfigurableSerializer != null)
- {
- var childSerializer = childSerializerConfigurableSerializer.ChildSerializer;
- var representationConfigurableChildSerializer = childSerializer as IRepresentationConfigurable;
- if (representationConfigurableChildSerializer != null)
- {
- var reconfiguredChildSerializer = representationConfigurableChildSerializer.WithRepresentation(_representation);
- var reconfiguredSerializer = childSerializerConfigurableSerializer.WithChildSerializer(reconfiguredChildSerializer);
- memberMap.SetSerializer(reconfiguredSerializer);
- }
- }
- return;
+ memberMap.SetSerializer(reconfiguredSerializer);
+ }
+ }
+
+ private IBsonSerializer Reconfigure(IBsonSerializer serializer)
+ {
+ if (serializer is IChildSerializerConfigurable childSerializerConfigurable)
+ {
+ var childSerializer = childSerializerConfigurable.ChildSerializer;
+ var reconfiguredChildSerializer = Reconfigure(childSerializer);
+ return reconfiguredChildSerializer is null ? null : childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer);
}
+
+ var serializerType = serializer.GetType();
+ if (serializerType.IsGenericType && serializerType.GetGenericTypeDefinition() == typeof(EnumSerializer<>))
+ {
+ return (serializer as IRepresentationConfigurable)?.WithRepresentation(_representation);
+ }
+
+ return null;
}
// private methods
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index bde58d6af76..520df844fee 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -14,6 +14,7 @@
*/
using System;
+using System.Collections.Generic;
using System.Linq.Expressions;
using FluentAssertions;
using MongoDB.Bson.Serialization;
@@ -31,7 +32,9 @@ public class C
{
public E E { get; set; }
public E? NE { get; set; }
+ public E[] ArrayEnum { get; set; }
public int I { get; set; }
+ public int[] ArrayInt { get; set; }
}
[Theory]
@@ -51,6 +54,8 @@ public void Apply_should_configure_serializer_when_member_is_an_enum(BsonType re
[Theory]
[InlineData(BsonType.Int32)]
[InlineData(BsonType.Int64)]
+ [InlineData(BsonType.String)]
+ //TODO we need a test like this for collections of various kinds (including dictionaries)
public void Apply_should_configure_serializer_when_member_is_a_nullable_enum(BsonType representation)
{
var subject = new EnumRepresentationConvention(representation);
@@ -63,6 +68,22 @@ public void Apply_should_configure_serializer_when_member_is_a_nullable_enum(Bso
childSerializer.Representation.Should().Be(representation);
}
+ [Theory]
+ [InlineData(BsonType.Int32)]
+ [InlineData(BsonType.Int64)]
+ [InlineData(BsonType.String)]
+ public void Apply_should_configure_serializer_when_member_is_an_enum_collection(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation);
+ var memberMap = CreateMemberMap(c => c.ArrayEnum);
+
+ subject.Apply(memberMap);
+
+ var serializer = (IChildSerializerConfigurable)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)serializer.ChildSerializer;
+ childSerializer.Representation.Should().Be(representation);
+ }
+
[Fact]
public void Apply_should_do_nothing_when_member_is_not_an_enum()
{
@@ -75,6 +96,18 @@ public void Apply_should_do_nothing_when_member_is_not_an_enum()
memberMap.GetSerializer().Should().BeSameAs(serializer);
}
+ [Fact]
+ public void Apply_should_do_nothing_when_member_is_not_an_enum_collection()
+ {
+ var subject = new EnumRepresentationConvention(BsonType.String);
+ var memberMap = CreateMemberMap(c => c.ArrayInt);
+ var serializer = memberMap.GetSerializer();
+
+ subject.Apply(memberMap);
+
+ memberMap.GetSerializer().Should().BeSameAs(serializer);
+ }
+
[Theory]
[InlineData((BsonType)0)]
[InlineData(BsonType.Int32)]
From 91daba729b27186f5ad2285b32fa5ea7354e147f Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Tue, 5 Nov 2024 18:15:15 +0100
Subject: [PATCH 02/19] Small fix plus added dictionary test
---
.../EnumRepresentationConvention.cs | 17 ++---------------
.../EnumRepresentationConventionTests.cs | 18 +++++++++++++++++-
2 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index f9c33973a28..4a1f4b4df4b 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -14,7 +14,6 @@
*/
using System;
-using System.Reflection;
using MongoDB.Bson.Serialization.Serializers;
namespace MongoDB.Bson.Serialization.Conventions
@@ -84,25 +83,13 @@ private IBsonSerializer Reconfigure(IBsonSerializer serializer)
}
// private methods
- private bool IsNullableEnum(Type type)
- {
- return
- type.GetTypeInfo().IsGenericType &&
- type.GetGenericTypeDefinition() == typeof(Nullable<>) &&
- Nullable.GetUnderlyingType(type).GetTypeInfo().IsEnum;
- }
-
private void EnsureRepresentationIsValidForEnums(BsonType representation)
{
- if (
- representation == 0 ||
- representation == BsonType.String ||
- representation == BsonType.Int32 ||
- representation == BsonType.Int64)
+ if (representation is 0 or BsonType.String or BsonType.Int32 or BsonType.Int64)
{
return;
}
- throw new ArgumentException("Enums can only be represented as String, Int32, Int64 or the type of the enum", "representation");
+ throw new ArgumentException("Enums can only be represented as String, Int32, Int64 or the type of the enum", nameof(representation));
}
}
}
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index 520df844fee..d6fbc9a5531 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -33,6 +33,7 @@ public class C
public E E { get; set; }
public E? NE { get; set; }
public E[] ArrayEnum { get; set; }
+ public Dictionary DictionaryEnum { get; set; }
public int I { get; set; }
public int[] ArrayInt { get; set; }
}
@@ -55,7 +56,6 @@ public void Apply_should_configure_serializer_when_member_is_an_enum(BsonType re
[InlineData(BsonType.Int32)]
[InlineData(BsonType.Int64)]
[InlineData(BsonType.String)]
- //TODO we need a test like this for collections of various kinds (including dictionaries)
public void Apply_should_configure_serializer_when_member_is_a_nullable_enum(BsonType representation)
{
var subject = new EnumRepresentationConvention(representation);
@@ -84,6 +84,22 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_collection(
childSerializer.Representation.Should().Be(representation);
}
+ [Theory]
+ [InlineData(BsonType.Int32)]
+ [InlineData(BsonType.Int64)]
+ [InlineData(BsonType.String)]
+ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation);
+ var memberMap = CreateMemberMap(c => c.DictionaryEnum);
+
+ subject.Apply(memberMap);
+
+ var serializer = (IChildSerializerConfigurable)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)serializer.ChildSerializer;
+ childSerializer.Representation.Should().Be(representation);
+ }
+
[Fact]
public void Apply_should_do_nothing_when_member_is_not_an_enum()
{
From cdce373358fd9de9fecf9eb475d46fc0584a3949 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Wed, 6 Nov 2024 09:05:59 +0100
Subject: [PATCH 03/19] Added nested tests
---
.../EnumRepresentationConventionTests.cs | 34 +++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index d6fbc9a5531..04375962c45 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -33,7 +33,9 @@ public class C
public E E { get; set; }
public E? NE { get; set; }
public E[] ArrayEnum { get; set; }
+ public E[][] ArrayOfArrayEnum { get; set; }
public Dictionary DictionaryEnum { get; set; }
+ public Dictionary NestedDictionaryEnum { get; set; }
public int I { get; set; }
public int[] ArrayInt { get; set; }
}
@@ -84,6 +86,22 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_collection(
childSerializer.Representation.Should().Be(representation);
}
+ [Theory]
+ [InlineData(BsonType.Int32)]
+ [InlineData(BsonType.Int64)]
+ [InlineData(BsonType.String)]
+ public void Apply_should_configure_serializer_when_member_is_a_nested_enum_collection(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation);
+ var memberMap = CreateMemberMap(c => c.ArrayOfArrayEnum);
+
+ subject.Apply(memberMap);
+
+ var serializer = (IChildSerializerConfigurable)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)((IChildSerializerConfigurable)serializer.ChildSerializer).ChildSerializer;
+ childSerializer.Representation.Should().Be(representation);
+ }
+
[Theory]
[InlineData(BsonType.Int32)]
[InlineData(BsonType.Int64)]
@@ -100,6 +118,22 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary(
childSerializer.Representation.Should().Be(representation);
}
+ [Theory]
+ [InlineData(BsonType.Int32)]
+ [InlineData(BsonType.Int64)]
+ [InlineData(BsonType.String)]
+ public void Apply_should_configure_serializer_when_member_is_a_nested_enum_dictionary(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation);
+ var memberMap = CreateMemberMap(c => c.NestedDictionaryEnum);
+
+ subject.Apply(memberMap);
+
+ var serializer = (IChildSerializerConfigurable)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)((IChildSerializerConfigurable)serializer.ChildSerializer).ChildSerializer;
+ childSerializer.Representation.Should().Be(representation);
+ }
+
[Fact]
public void Apply_should_do_nothing_when_member_is_not_an_enum()
{
From f8078536da8787c6f7280dbf2aca37f97369d04b Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Fri, 15 Nov 2024 09:53:09 +0100
Subject: [PATCH 04/19] Small improvement
---
.../Conventions/EnumRepresentationConvention.cs | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index 4a1f4b4df4b..842509966d5 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -73,10 +73,9 @@ private IBsonSerializer Reconfigure(IBsonSerializer serializer)
return reconfiguredChildSerializer is null ? null : childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer);
}
- var serializerType = serializer.GetType();
- if (serializerType.IsGenericType && serializerType.GetGenericTypeDefinition() == typeof(EnumSerializer<>))
+ if (serializer.ValueType.IsEnum && serializer is IRepresentationConfigurable representationConfigurable)
{
- return (serializer as IRepresentationConfigurable)?.WithRepresentation(_representation);
+ return representationConfigurable.WithRepresentation(_representation);
}
return null;
From d7b1739e1b30f3e17e31fc52515e6c896796a5aa Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 12 Dec 2024 11:53:04 -0500
Subject: [PATCH 05/19] Corrections
---
.../EnumRepresentationConvention.cs | 38 +++++++++++++++++--
.../EnumRepresentationConventionTests.cs | 38 ++++++++++++++++---
2 files changed, 67 insertions(+), 9 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index 842509966d5..efcd06285a4 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -14,7 +14,7 @@
*/
using System;
-using MongoDB.Bson.Serialization.Serializers;
+using System.Reflection;
namespace MongoDB.Bson.Serialization.Conventions
{
@@ -25,6 +25,7 @@ public class EnumRepresentationConvention : ConventionBase, IMemberMapConvention
{
// private fields
private readonly BsonType _representation;
+ private readonly bool _shouldApplyToCollections;
// constructors
///
@@ -33,9 +34,21 @@ public class EnumRepresentationConvention : ConventionBase, IMemberMapConvention
/// The serialization representation. 0 is used to detect representation
/// from the enum itself.
public EnumRepresentationConvention(BsonType representation)
+ :this(representation, false)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The serialization representation. 0 is used to detect representation
+ /// from the enum itself.
+ /// If set to true, the convention will be applied also to collection of enums, recursively.
+ public EnumRepresentationConvention(BsonType representation, bool shouldApplyToCollections)
{
EnsureRepresentationIsValidForEnums(representation);
_representation = representation;
+ _shouldApplyToCollections = shouldApplyToCollections;
}
///
@@ -43,6 +56,11 @@ public EnumRepresentationConvention(BsonType representation)
///
public BsonType Representation => _representation;
+ ///
+ /// Gets a boolean indicating if this convention should be also applied to collections of enums.
+ ///
+ public bool ShouldApplyToCollections => _shouldApplyToCollections;
+
///
/// Applies a modification to the member map.
///
@@ -57,10 +75,13 @@ public void Apply(BsonMemberMap memberMap)
return;
}
- var reconfiguredSerializer = Reconfigure(serializer);
- if (reconfiguredSerializer is not null)
+ if (_shouldApplyToCollections || IsNullableEnum(memberMap.MemberType))
{
- memberMap.SetSerializer(reconfiguredSerializer);
+ var reconfiguredSerializer = Reconfigure(serializer);
+ if (reconfiguredSerializer is not null)
+ {
+ memberMap.SetSerializer(reconfiguredSerializer);
+ }
}
}
@@ -82,6 +103,15 @@ private IBsonSerializer Reconfigure(IBsonSerializer serializer)
}
// private methods
+ // private methods
+ private bool IsNullableEnum(Type type)
+ {
+ return
+ type.GetTypeInfo().IsGenericType &&
+ type.GetGenericTypeDefinition() == typeof(Nullable<>) &&
+ Nullable.GetUnderlyingType(type)!.GetTypeInfo().IsEnum;
+ }
+
private void EnsureRepresentationIsValidForEnums(BsonType representation)
{
if (representation is 0 or BsonType.String or BsonType.Int32 or BsonType.Int64)
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index 04375962c45..827282020a5 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -20,6 +20,7 @@
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Bson.Serialization.Serializers;
+using MongoDB.TestHelpers.XunitExtensions;
using Xunit;
namespace MongoDB.Bson.Tests.Serialization.Conventions
@@ -76,7 +77,7 @@ public void Apply_should_configure_serializer_when_member_is_a_nullable_enum(Bso
[InlineData(BsonType.String)]
public void Apply_should_configure_serializer_when_member_is_an_enum_collection(BsonType representation)
{
- var subject = new EnumRepresentationConvention(representation);
+ var subject = new EnumRepresentationConvention(representation, true);
var memberMap = CreateMemberMap(c => c.ArrayEnum);
subject.Apply(memberMap);
@@ -92,7 +93,7 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_collection(
[InlineData(BsonType.String)]
public void Apply_should_configure_serializer_when_member_is_a_nested_enum_collection(BsonType representation)
{
- var subject = new EnumRepresentationConvention(representation);
+ var subject = new EnumRepresentationConvention(representation, true);
var memberMap = CreateMemberMap(c => c.ArrayOfArrayEnum);
subject.Apply(memberMap);
@@ -108,7 +109,7 @@ public void Apply_should_configure_serializer_when_member_is_a_nested_enum_colle
[InlineData(BsonType.String)]
public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary(BsonType representation)
{
- var subject = new EnumRepresentationConvention(representation);
+ var subject = new EnumRepresentationConvention(representation, true);
var memberMap = CreateMemberMap(c => c.DictionaryEnum);
subject.Apply(memberMap);
@@ -124,7 +125,7 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary(
[InlineData(BsonType.String)]
public void Apply_should_configure_serializer_when_member_is_a_nested_enum_dictionary(BsonType representation)
{
- var subject = new EnumRepresentationConvention(representation);
+ var subject = new EnumRepresentationConvention(representation, true);
var memberMap = CreateMemberMap(c => c.NestedDictionaryEnum);
subject.Apply(memberMap);
@@ -134,6 +135,21 @@ public void Apply_should_configure_serializer_when_member_is_a_nested_enum_dicti
childSerializer.Representation.Should().Be(representation);
}
+ [Theory]
+ [InlineData(BsonType.Int64)]
+ [InlineData(BsonType.String)]
+ public void Apply_should_do_nothing_when_member_is_an_enum_collection_and_should_apply_to_collection_is_false(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation, false);
+ var memberMap = CreateMemberMap(c => c.ArrayEnum);
+
+ subject.Apply(memberMap);
+
+ var serializer = (IChildSerializerConfigurable)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)serializer.ChildSerializer;
+ childSerializer.Representation.Should().Be(BsonType.Int32);
+ }
+
[Fact]
public void Apply_should_do_nothing_when_member_is_not_an_enum()
{
@@ -163,13 +179,25 @@ public void Apply_should_do_nothing_when_member_is_not_an_enum_collection()
[InlineData(BsonType.Int32)]
[InlineData(BsonType.Int64)]
[InlineData(BsonType.String)]
- public void constructor_should_initialize_instance_when_representation_is_valid(BsonType representation)
+ public void constructor_with_representation_should_return_expected_result(BsonType representation)
{
var subject = new EnumRepresentationConvention(representation);
subject.Representation.Should().Be(representation);
}
+ [Theory]
+ [ParameterAttributeData]
+ public void constructor_with_representation_and_should_apply_to_collection_should_return_expected_result(
+ [Values((BsonType)0, BsonType.Int32, BsonType.Int64, BsonType.String)] BsonType representation,
+ [Values(true, false)] bool shouldApplyToCollections)
+ {
+ var subject = new EnumRepresentationConvention(representation, shouldApplyToCollections);
+
+ subject.Representation.Should().Be(representation);
+ subject.ShouldApplyToCollections.Should().Be(shouldApplyToCollections);
+ }
+
[Theory]
[InlineData(BsonType.Decimal128)]
[InlineData(BsonType.Double)]
From 6fd00005ef9fb2db2dfdc314858a4eb63e2745b4 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Mon, 16 Dec 2024 10:27:48 +0100
Subject: [PATCH 06/19] Corrections according to PR
---
.../Conventions/EnumRepresentationConvention.cs | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index efcd06285a4..1b82f054d05 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -102,14 +102,13 @@ private IBsonSerializer Reconfigure(IBsonSerializer serializer)
return null;
}
- // private methods
// private methods
private bool IsNullableEnum(Type type)
{
return
- type.GetTypeInfo().IsGenericType &&
+ type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof(Nullable<>) &&
- Nullable.GetUnderlyingType(type)!.GetTypeInfo().IsEnum;
+ Nullable.GetUnderlyingType(type)!.IsEnum;
}
private void EnsureRepresentationIsValidForEnums(BsonType representation)
From 5378c0ca337e008ea488334194083deb5527cfbb Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Tue, 17 Dec 2024 09:36:18 +0100
Subject: [PATCH 07/19] Small fix
---
.../Serialization/Conventions/EnumRepresentationConvention.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index 1b82f054d05..80fbd8b87fb 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -14,7 +14,6 @@
*/
using System;
-using System.Reflection;
namespace MongoDB.Bson.Serialization.Conventions
{
@@ -87,7 +86,7 @@ public void Apply(BsonMemberMap memberMap)
private IBsonSerializer Reconfigure(IBsonSerializer serializer)
{
- if (serializer is IChildSerializerConfigurable childSerializerConfigurable)
+ if (serializer is IBsonArraySerializer and IChildSerializerConfigurable childSerializerConfigurable)
{
var childSerializer = childSerializerConfigurable.ChildSerializer;
var reconfiguredChildSerializer = Reconfigure(childSerializer);
From 6b817305097dc423094bb3e62acdff3c6489c7c6 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Tue, 17 Dec 2024 10:28:32 +0100
Subject: [PATCH 08/19] Corrected calls
---
.../EnumRepresentationConvention.cs | 44 +++----------------
.../Serialization/SerializerConfigurator.cs | 18 +++++---
2 files changed, 17 insertions(+), 45 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index 80fbd8b87fb..7a7d17055e7 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -66,50 +66,18 @@ public EnumRepresentationConvention(BsonType representation, bool shouldApplyToC
/// The member map.
public void Apply(BsonMemberMap memberMap)
{
- var serializer = memberMap.GetSerializer();
+ var reconfiguredSerializer =
+ SerializerConfigurator.ReconfigureSerializer(memberMap.GetSerializer(),
+ s => s.WithRepresentation(_representation),
+ s => s.ValueType.IsEnum, _shouldApplyToCollections);
- if (memberMap.MemberType.IsEnum && serializer is IRepresentationConfigurable representationConfigurableSerializer)
+ if (reconfiguredSerializer is not null)
{
- memberMap.SetSerializer(representationConfigurableSerializer.WithRepresentation(_representation));
- return;
- }
-
- if (_shouldApplyToCollections || IsNullableEnum(memberMap.MemberType))
- {
- var reconfiguredSerializer = Reconfigure(serializer);
- if (reconfiguredSerializer is not null)
- {
- memberMap.SetSerializer(reconfiguredSerializer);
- }
- }
- }
-
- private IBsonSerializer Reconfigure(IBsonSerializer serializer)
- {
- if (serializer is IBsonArraySerializer and IChildSerializerConfigurable childSerializerConfigurable)
- {
- var childSerializer = childSerializerConfigurable.ChildSerializer;
- var reconfiguredChildSerializer = Reconfigure(childSerializer);
- return reconfiguredChildSerializer is null ? null : childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer);
- }
-
- if (serializer.ValueType.IsEnum && serializer is IRepresentationConfigurable representationConfigurable)
- {
- return representationConfigurable.WithRepresentation(_representation);
+ memberMap.SetSerializer(reconfiguredSerializer);
}
-
- return null;
}
// private methods
- private bool IsNullableEnum(Type type)
- {
- return
- type.IsGenericType &&
- type.GetGenericTypeDefinition() == typeof(Nullable<>) &&
- Nullable.GetUnderlyingType(type)!.IsEnum;
- }
-
private void EnsureRepresentationIsValidForEnums(BsonType representation)
{
if (representation is 0 or BsonType.String or BsonType.Int32 or BsonType.Int64)
diff --git a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
index 7e1cfbecbe5..2ff010957b2 100644
--- a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
+++ b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
@@ -26,22 +26,26 @@ internal static class SerializerConfigurator
///
/// The input serializer to be reconfigured.
/// A function that defines how the serializer of type should be reconfigured.
+ /// TODO
+ /// TODO
/// The input type for the reconfigure method.
///
/// The reconfigured serializer, or null if no leaf serializer could be reconfigured.
///
- internal static IBsonSerializer ReconfigureSerializer(IBsonSerializer serializer, Func reconfigure)
+ internal static IBsonSerializer ReconfigureSerializer(IBsonSerializer serializer, Func reconfigure,
+ Func testFunc = null, bool shouldApplyToCollections = true)
{
switch (serializer)
{
- case IChildSerializerConfigurable childSerializerConfigurable:
+ case TSerializer typedSerializer when testFunc?.Invoke(serializer) ?? true:
+ return reconfigure(typedSerializer);
+ case IChildSerializerConfigurable childSerializerConfigurable when
+ shouldApplyToCollections || Nullable.GetUnderlyingType(serializer.ValueType) != null:
+ {
var childSerializer = childSerializerConfigurable.ChildSerializer;
- var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure);
+ var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunc, shouldApplyToCollections);
return reconfiguredChildSerializer != null? childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer) : null;
-
- case TSerializer typedSerializer:
- return reconfigure(typedSerializer);
-
+ }
default:
return null;
}
From db6362329f103d9aef98d210145e501f5c16b175 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Tue, 17 Dec 2024 11:58:33 +0100
Subject: [PATCH 09/19] Corrections
---
.../IKeyAndValueSerializerConfigurable.cs | 31 ++++++++++++++
.../Serialization/SerializerConfigurator.cs | 41 +++++++++++--------
...ictionaryInterfaceImplementerSerializer.cs | 16 ++++++++
...ictionaryInterfaceImplementerSerializer.cs | 8 ++++
.../EnumRepresentationConventionTests.cs | 18 ++++++++
5 files changed, 97 insertions(+), 17 deletions(-)
create mode 100644 src/MongoDB.Bson/Serialization/IKeyAndValueSerializerConfigurable.cs
diff --git a/src/MongoDB.Bson/Serialization/IKeyAndValueSerializerConfigurable.cs b/src/MongoDB.Bson/Serialization/IKeyAndValueSerializerConfigurable.cs
new file mode 100644
index 00000000000..4c54f441269
--- /dev/null
+++ b/src/MongoDB.Bson/Serialization/IKeyAndValueSerializerConfigurable.cs
@@ -0,0 +1,31 @@
+/* Copyright 2010-present MongoDB Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace MongoDB.Bson.Serialization
+{
+ ///
+ /// Represents a serializer that has a key and a value serializer that configuration attributes can be forwarded to.
+ ///
+ public interface IKeyAndValueSerializerConfigurable : IBsonDictionarySerializer
+ {
+ ///
+ /// Returns a serializer that has been reconfigured with the specified key and value serializers.
+ ///
+ /// The key serializer.
+ /// The value serializer.
+ /// The reconfigured serializer.
+ IBsonSerializer WithKeyAndValueSerializers(IBsonSerializer keySerializer, IBsonSerializer valueSerializer);
+ }
+}
\ No newline at end of file
diff --git a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
index 2ff010957b2..fb64f5977d7 100644
--- a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
+++ b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
@@ -19,31 +19,38 @@ namespace MongoDB.Bson.Serialization
{
internal static class SerializerConfigurator
{
- ///
- /// Reconfigures a serializer using the specified method.
- /// If the serializer implements ,
- /// the method traverses and applies the reconfiguration to its child serializers recursively until an appropriate leaf serializer is found.
- ///
- /// The input serializer to be reconfigured.
- /// A function that defines how the serializer of type should be reconfigured.
- /// TODO
- /// TODO
- /// The input type for the reconfigure method.
- ///
- /// The reconfigured serializer, or null if no leaf serializer could be reconfigured.
- ///
+ /// Reconfigures a serializer using the specified method if the result of is true or the function is null.
+ /// If the serializer implements and either:
+ /// - is a collection serializer and is true;
+ /// - or is a serializer;
+ /// the method traverses and applies the reconfiguration to its child serializers recursively.
internal static IBsonSerializer ReconfigureSerializer(IBsonSerializer serializer, Func reconfigure,
- Func testFunc = null, bool shouldApplyToCollections = true)
+ Func testFunction = null, bool shouldApplyToCollections = true)
{
switch (serializer)
{
- case TSerializer typedSerializer when testFunc?.Invoke(serializer) ?? true:
+ case TSerializer typedSerializer when testFunction?.Invoke(serializer) ?? true:
return reconfigure(typedSerializer);
case IChildSerializerConfigurable childSerializerConfigurable when
- shouldApplyToCollections || Nullable.GetUnderlyingType(serializer.ValueType) != null:
+ (shouldApplyToCollections && childSerializerConfigurable is IBsonArraySerializer)
+ || Nullable.GetUnderlyingType(serializer.ValueType) != null:
{
+ if (childSerializerConfigurable is IKeyAndValueSerializerConfigurable keyAndValueSerializerConfigurable)
+ {
+ var keySerializer = keyAndValueSerializerConfigurable.KeySerializer;
+ var valueSerializer = keyAndValueSerializerConfigurable.ValueSerializer;
+
+ var reconfiguredKeySerializer = ReconfigureSerializer(keySerializer, reconfigure, testFunction,
+ shouldApplyToCollections);
+ var reconfiguredValueSerializer = ReconfigureSerializer(valueSerializer, reconfigure, testFunction,
+ shouldApplyToCollections);
+
+ return keyAndValueSerializerConfigurable.WithKeyAndValueSerializers(
+ reconfiguredKeySerializer ?? keySerializer, reconfiguredValueSerializer ?? valueSerializer);
+ }
+
var childSerializer = childSerializerConfigurable.ChildSerializer;
- var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunc, shouldApplyToCollections);
+ var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunction, shouldApplyToCollections);
return reconfiguredChildSerializer != null? childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer) : null;
}
default:
diff --git a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
index d188eb1c9fe..1bf689c8a65 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
@@ -27,6 +27,7 @@ namespace MongoDB.Bson.Serialization.Serializers
public sealed class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
+ IKeyAndValueSerializerConfigurable,
IDictionaryRepresentationConfigurable
where TDictionary : class, IDictionary, new()
{
@@ -153,6 +154,13 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
{
return WithDictionaryRepresentation(dictionaryRepresentation);
}
+
+ IBsonSerializer IKeyAndValueSerializerConfigurable.WithKeyAndValueSerializers(IBsonSerializer keySerializer, IBsonSerializer valueSerializer)
+ {
+ return valueSerializer.Equals(ValueSerializer) && keySerializer.Equals(KeySerializer)
+ ? this
+ : new DictionaryInterfaceImplementerSerializer(DictionaryRepresentation, keySerializer, valueSerializer);
+ }
}
///
@@ -164,6 +172,7 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
public class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
+ IKeyAndValueSerializerConfigurable,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IDictionary
{
@@ -281,6 +290,13 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
+ IBsonSerializer IKeyAndValueSerializerConfigurable.WithKeyAndValueSerializers(IBsonSerializer keySerializer, IBsonSerializer valueSerializer)
+ {
+ return valueSerializer.Equals(ValueSerializer) && keySerializer.Equals(KeySerializer)
+ ? this
+ : new DictionaryInterfaceImplementerSerializer(DictionaryRepresentation, (IBsonSerializer)keySerializer, (IBsonSerializer)valueSerializer);
+ }
+
///
protected override ICollection> CreateAccumulator()
{
diff --git a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
index ae2b7479221..1effe8da3ea 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
@@ -28,6 +28,7 @@ namespace MongoDB.Bson.Serialization.Serializers
public sealed class ReadOnlyDictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
+ IKeyAndValueSerializerConfigurable,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IReadOnlyDictionary
{
@@ -122,6 +123,13 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
+ IBsonSerializer IKeyAndValueSerializerConfigurable.WithKeyAndValueSerializers(IBsonSerializer keySerializer, IBsonSerializer valueSerializer)
+ {
+ return valueSerializer.Equals(ValueSerializer) && keySerializer.Equals(KeySerializer)
+ ? this
+ : new ReadOnlyDictionaryInterfaceImplementerSerializer(DictionaryRepresentation, (IBsonSerializer)keySerializer, (IBsonSerializer)valueSerializer);
+ }
+
///
protected override ICollection> CreateAccumulator()
{
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index 827282020a5..3e718e60a07 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -37,6 +37,8 @@ public class C
public E[][] ArrayOfArrayEnum { get; set; }
public Dictionary DictionaryEnum { get; set; }
public Dictionary NestedDictionaryEnum { get; set; }
+
+ public Dictionary DictionaryKeyEnum { get; set; }
public int I { get; set; }
public int[] ArrayInt { get; set; }
}
@@ -119,6 +121,22 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary(
childSerializer.Representation.Should().Be(representation);
}
+ [Theory]
+ [InlineData(BsonType.Int32)]
+ [InlineData(BsonType.Int64)]
+ [InlineData(BsonType.String)]
+ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary_key(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation, true);
+ var memberMap = CreateMemberMap(c => c.DictionaryKeyEnum);
+
+ subject.Apply(memberMap);
+
+ var serializer = (IKeyAndValueSerializerConfigurable)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)serializer.KeySerializer;
+ childSerializer.Representation.Should().Be(representation);
+ }
+
[Theory]
[InlineData(BsonType.Int32)]
[InlineData(BsonType.Int64)]
From 48c71a9e2e2a56c4b45183fd5ad89f6ac1f461dd Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Tue, 17 Dec 2024 17:07:48 +0100
Subject: [PATCH 10/19] Added test
---
.../EnumRepresentationConventionTests.cs | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index 3e718e60a07..cdc6dde27d4 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -37,9 +37,9 @@ public class C
public E[][] ArrayOfArrayEnum { get; set; }
public Dictionary DictionaryEnum { get; set; }
public Dictionary NestedDictionaryEnum { get; set; }
-
public Dictionary DictionaryKeyEnum { get; set; }
public int I { get; set; }
+ public int NI { get; set; }
public int[] ArrayInt { get; set; }
}
@@ -180,6 +180,18 @@ public void Apply_should_do_nothing_when_member_is_not_an_enum()
memberMap.GetSerializer().Should().BeSameAs(serializer);
}
+ [Fact]
+ public void Apply_should_do_nothing_when_member_is_not_an_enum_and_nullable()
+ {
+ var subject = new EnumRepresentationConvention(BsonType.String);
+ var memberMap = CreateMemberMap(c => c.NI);
+ var serializer = memberMap.GetSerializer();
+
+ subject.Apply(memberMap);
+
+ memberMap.GetSerializer().Should().BeSameAs(serializer);
+ }
+
[Fact]
public void Apply_should_do_nothing_when_member_is_not_an_enum_collection()
{
From faf6095d68cd67126e9dc881c052b0762edb7ed8 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Fri, 20 Dec 2024 14:14:49 +0100
Subject: [PATCH 11/19] Various corrections
---
...ildrenSerializerConfigurableSerializer.cs} | 19 +++++++---
.../Serialization/SerializerConfigurator.cs | 29 +++++++-------
...ictionaryInterfaceImplementerSerializer.cs | 38 +++++++++++++++----
...ictionaryInterfaceImplementerSerializer.cs | 19 ++++++++--
.../EnumRepresentationConventionTests.cs | 6 +--
5 files changed, 76 insertions(+), 35 deletions(-)
rename src/MongoDB.Bson/Serialization/{IKeyAndValueSerializerConfigurable.cs => IMultipleChildrenSerializerConfigurableSerializer.cs} (57%)
diff --git a/src/MongoDB.Bson/Serialization/IKeyAndValueSerializerConfigurable.cs b/src/MongoDB.Bson/Serialization/IMultipleChildrenSerializerConfigurableSerializer.cs
similarity index 57%
rename from src/MongoDB.Bson/Serialization/IKeyAndValueSerializerConfigurable.cs
rename to src/MongoDB.Bson/Serialization/IMultipleChildrenSerializerConfigurableSerializer.cs
index 4c54f441269..b73fb2d76c2 100644
--- a/src/MongoDB.Bson/Serialization/IKeyAndValueSerializerConfigurable.cs
+++ b/src/MongoDB.Bson/Serialization/IMultipleChildrenSerializerConfigurableSerializer.cs
@@ -16,16 +16,23 @@
namespace MongoDB.Bson.Serialization
{
///
- /// Represents a serializer that has a key and a value serializer that configuration attributes can be forwarded to.
+ /// Represents a serializer that has multiple children serializers that configuration attributes can be forwarded to.
///
- public interface IKeyAndValueSerializerConfigurable : IBsonDictionarySerializer
+ public interface IMultipleChildrenSerializerConfigurableSerializer
{
///
- /// Returns a serializer that has been reconfigured with the specified key and value serializers.
+ /// Gets the children serializers.
///
- /// The key serializer.
- /// The value serializer.
+ ///
+ /// The children serializers.
+ ///
+ IBsonSerializer[] ChildrenSerializers { get; }
+
+ ///
+ /// Returns a serializer that has been reconfigured with the specified children serializers.
+ ///
+ /// The children serializers.
/// The reconfigured serializer.
- IBsonSerializer WithKeyAndValueSerializers(IBsonSerializer keySerializer, IBsonSerializer valueSerializer);
+ IBsonSerializer WithChildrenSerializers(IBsonSerializer[] childrenSerializers);
}
}
\ No newline at end of file
diff --git a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
index fb64f5977d7..869ee2715e2 100644
--- a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
+++ b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
@@ -14,6 +14,7 @@
*/
using System;
+using System.Collections.Generic;
namespace MongoDB.Bson.Serialization
{
@@ -21,7 +22,7 @@ internal static class SerializerConfigurator
{
/// Reconfigures a serializer using the specified method if the result of is true or the function is null.
/// If the serializer implements and either:
- /// - is a collection serializer and is true;
+ /// - is true;
/// - or is a serializer;
/// the method traverses and applies the reconfiguration to its child serializers recursively.
internal static IBsonSerializer ReconfigureSerializer(IBsonSerializer serializer, Func reconfigure,
@@ -31,28 +32,28 @@ internal static IBsonSerializer ReconfigureSerializer(IBsonSerializ
{
case TSerializer typedSerializer when testFunction?.Invoke(serializer) ?? true:
return reconfigure(typedSerializer);
- case IChildSerializerConfigurable childSerializerConfigurable when
- (shouldApplyToCollections && childSerializerConfigurable is IBsonArraySerializer)
- || Nullable.GetUnderlyingType(serializer.ValueType) != null:
+ case IMultipleChildrenSerializerConfigurableSerializer multipleChildrenSerializerConfigurable:
{
- if (childSerializerConfigurable is IKeyAndValueSerializerConfigurable keyAndValueSerializerConfigurable)
- {
- var keySerializer = keyAndValueSerializerConfigurable.KeySerializer;
- var valueSerializer = keyAndValueSerializerConfigurable.ValueSerializer;
+ var newSerializers = new List();
- var reconfiguredKeySerializer = ReconfigureSerializer(keySerializer, reconfigure, testFunction,
- shouldApplyToCollections);
- var reconfiguredValueSerializer = ReconfigureSerializer(valueSerializer, reconfigure, testFunction,
+ foreach (var childSerializer in multipleChildrenSerializerConfigurable.ChildrenSerializers)
+ {
+ var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunction,
shouldApplyToCollections);
- return keyAndValueSerializerConfigurable.WithKeyAndValueSerializers(
- reconfiguredKeySerializer ?? keySerializer, reconfiguredValueSerializer ?? valueSerializer);
+ newSerializers.Add(reconfiguredChildSerializer ?? childSerializer);
}
-
+
+ return multipleChildrenSerializerConfigurable.WithChildrenSerializers(newSerializers.ToArray());
+ }
+ case IChildSerializerConfigurable childSerializerConfigurable when
+ shouldApplyToCollections || Nullable.GetUnderlyingType(serializer.ValueType) != null:
+ {
var childSerializer = childSerializerConfigurable.ChildSerializer;
var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunction, shouldApplyToCollections);
return reconfiguredChildSerializer != null? childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer) : null;
}
+
default:
return null;
}
diff --git a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
index 1bf689c8a65..cee58b8f9e3 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
@@ -27,7 +27,7 @@ namespace MongoDB.Bson.Serialization.Serializers
public sealed class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
- IKeyAndValueSerializerConfigurable,
+ IMultipleChildrenSerializerConfigurableSerializer,
IDictionaryRepresentationConfigurable
where TDictionary : class, IDictionary, new()
{
@@ -155,11 +155,22 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
- IBsonSerializer IKeyAndValueSerializerConfigurable.WithKeyAndValueSerializers(IBsonSerializer keySerializer, IBsonSerializer valueSerializer)
+ IBsonSerializer[] IMultipleChildrenSerializerConfigurableSerializer.ChildrenSerializers => [KeySerializer, ValueSerializer];
+
+ IBsonSerializer IMultipleChildrenSerializerConfigurableSerializer.WithChildrenSerializers(IBsonSerializer[] childrenSerializers)
{
- return valueSerializer.Equals(ValueSerializer) && keySerializer.Equals(KeySerializer)
+ if (childrenSerializers.Length != 2)
+ {
+ throw new Exception("Wrong number of children serializers passed.");
+ }
+
+ var newKeySerializer = childrenSerializers[0];
+ var newValueSerializer = childrenSerializers[1];
+
+ return newKeySerializer.Equals(KeySerializer) && newValueSerializer.Equals(ValueSerializer)
? this
- : new DictionaryInterfaceImplementerSerializer(DictionaryRepresentation, keySerializer, valueSerializer);
+ : new DictionaryInterfaceImplementerSerializer(DictionaryRepresentation, newKeySerializer,
+ newValueSerializer);
}
}
@@ -172,7 +183,7 @@ IBsonSerializer IKeyAndValueSerializerConfigurable.WithKeyAndValueSerializers(IB
public class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
- IKeyAndValueSerializerConfigurable,
+ IMultipleChildrenSerializerConfigurableSerializer,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IDictionary
{
@@ -290,11 +301,22 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
- IBsonSerializer IKeyAndValueSerializerConfigurable.WithKeyAndValueSerializers(IBsonSerializer keySerializer, IBsonSerializer valueSerializer)
+ IBsonSerializer[] IMultipleChildrenSerializerConfigurableSerializer.ChildrenSerializers => [KeySerializer, ValueSerializer];
+
+ IBsonSerializer IMultipleChildrenSerializerConfigurableSerializer.WithChildrenSerializers(IBsonSerializer[] childrenSerializers)
{
- return valueSerializer.Equals(ValueSerializer) && keySerializer.Equals(KeySerializer)
+ if (childrenSerializers.Length != 2)
+ {
+ throw new Exception("Wrong number of children serializers passed.");
+ }
+
+ var newKeySerializer = (IBsonSerializer)childrenSerializers[0];
+ var newValueSerializer = (IBsonSerializer)childrenSerializers[1];
+
+ return newKeySerializer.Equals(KeySerializer) && newValueSerializer.Equals(ValueSerializer)
? this
- : new DictionaryInterfaceImplementerSerializer(DictionaryRepresentation, (IBsonSerializer)keySerializer, (IBsonSerializer)valueSerializer);
+ : new DictionaryInterfaceImplementerSerializer(DictionaryRepresentation, newKeySerializer,
+ newValueSerializer);
}
///
diff --git a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
index 1effe8da3ea..436e1de10b4 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
@@ -28,7 +28,7 @@ namespace MongoDB.Bson.Serialization.Serializers
public sealed class ReadOnlyDictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
- IKeyAndValueSerializerConfigurable,
+ IMultipleChildrenSerializerConfigurableSerializer,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IReadOnlyDictionary
{
@@ -123,11 +123,22 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
- IBsonSerializer IKeyAndValueSerializerConfigurable.WithKeyAndValueSerializers(IBsonSerializer keySerializer, IBsonSerializer valueSerializer)
+ IBsonSerializer[] IMultipleChildrenSerializerConfigurableSerializer.ChildrenSerializers => [KeySerializer, ValueSerializer];
+
+ IBsonSerializer IMultipleChildrenSerializerConfigurableSerializer.WithChildrenSerializers(IBsonSerializer[] childrenSerializers)
{
- return valueSerializer.Equals(ValueSerializer) && keySerializer.Equals(KeySerializer)
+ if (childrenSerializers.Length != 2)
+ {
+ throw new Exception("Wrong number of children serializers passed.");
+ }
+
+ var newKeySerializer = (IBsonSerializer)childrenSerializers[0];
+ var newValueSerializer = (IBsonSerializer)childrenSerializers[1];
+
+ return newKeySerializer.Equals(KeySerializer) && newValueSerializer.Equals(ValueSerializer)
? this
- : new ReadOnlyDictionaryInterfaceImplementerSerializer(DictionaryRepresentation, (IBsonSerializer)keySerializer, (IBsonSerializer)valueSerializer);
+ : new ReadOnlyDictionaryInterfaceImplementerSerializer(DictionaryRepresentation, newKeySerializer,
+ newValueSerializer);
}
///
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index cdc6dde27d4..1454d2ba26a 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -132,8 +132,8 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary_
subject.Apply(memberMap);
- var serializer = (IKeyAndValueSerializerConfigurable)memberMap.GetSerializer();
- var childSerializer = (EnumSerializer)serializer.KeySerializer;
+ var serializer = (IMultipleChildrenSerializerConfigurableSerializer)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)serializer.ChildrenSerializers[0];
childSerializer.Representation.Should().Be(representation);
}
@@ -141,7 +141,7 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary_
[InlineData(BsonType.Int32)]
[InlineData(BsonType.Int64)]
[InlineData(BsonType.String)]
- public void Apply_should_configure_serializer_when_member_is_a_nested_enum_dictionary(BsonType representation)
+ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary_value(BsonType representation)
{
var subject = new EnumRepresentationConvention(representation, true);
var memberMap = CreateMemberMap(c => c.NestedDictionaryEnum);
From 9f9402534a36fd8568cc58d2645cc2cedd082e45 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Fri, 20 Dec 2024 14:29:09 +0100
Subject: [PATCH 12/19] Variable name change
---
.../BsonDateOnlyOptionsAttribute.cs | 2 +-
.../EnumRepresentationConvention.cs | 17 ++++++++--------
.../Serialization/SerializerConfigurator.cs | 12 +++++------
.../EnumRepresentationConventionTests.cs | 20 +++++++++----------
4 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs b/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs
index 34ed457ddd8..ac7be35e386 100644
--- a/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs
+++ b/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs
@@ -61,7 +61,7 @@ public BsonDateOnlyOptionsAttribute(BsonType representation, DateOnlyDocumentFor
/// A reconfigured serializer.
protected override IBsonSerializer Apply(IBsonSerializer serializer)
{
- var reconfiguredSerializer = SerializerConfigurator.ReconfigureSerializer(serializer, (DateOnlySerializer s) => s.WithRepresentation(_representation, _documentFormat));
+ var reconfiguredSerializer = SerializerConfigurator.ReconfigureSerializer(serializer, (DateOnlySerializer s) => s.WithRepresentation(_representation, _documentFormat), topLevelOnly: false);
return reconfiguredSerializer ?? base.Apply(serializer);
}
}
diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index 7a7d17055e7..ca7dabd4afc 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -24,7 +24,7 @@ public class EnumRepresentationConvention : ConventionBase, IMemberMapConvention
{
// private fields
private readonly BsonType _representation;
- private readonly bool _shouldApplyToCollections;
+ private readonly bool _topLevelOnly;
// constructors
///
@@ -33,7 +33,7 @@ public class EnumRepresentationConvention : ConventionBase, IMemberMapConvention
/// The serialization representation. 0 is used to detect representation
/// from the enum itself.
public EnumRepresentationConvention(BsonType representation)
- :this(representation, false)
+ :this(representation, true)
{
}
@@ -42,12 +42,12 @@ public EnumRepresentationConvention(BsonType representation)
///
/// The serialization representation. 0 is used to detect representation
/// from the enum itself.
- /// If set to true, the convention will be applied also to collection of enums, recursively.
- public EnumRepresentationConvention(BsonType representation, bool shouldApplyToCollections)
+ /// If set to true, the convention will be applied only to top level enum properties, and not collections of enums, for example.
+ public EnumRepresentationConvention(BsonType representation, bool topLevelOnly)
{
EnsureRepresentationIsValidForEnums(representation);
_representation = representation;
- _shouldApplyToCollections = shouldApplyToCollections;
+ _topLevelOnly = topLevelOnly;
}
///
@@ -56,9 +56,10 @@ public EnumRepresentationConvention(BsonType representation, bool shouldApplyToC
public BsonType Representation => _representation;
///
- /// Gets a boolean indicating if this convention should be also applied to collections of enums.
+ /// Gets a boolean indicating if this convention should be also applied only to the top level enum properties and not to others,
+ /// collections of enums for example. True by default.
///
- public bool ShouldApplyToCollections => _shouldApplyToCollections;
+ public bool TopLevelOnly => _topLevelOnly;
///
/// Applies a modification to the member map.
@@ -69,7 +70,7 @@ public void Apply(BsonMemberMap memberMap)
var reconfiguredSerializer =
SerializerConfigurator.ReconfigureSerializer(memberMap.GetSerializer(),
s => s.WithRepresentation(_representation),
- s => s.ValueType.IsEnum, _shouldApplyToCollections);
+ s => s.ValueType.IsEnum, _topLevelOnly);
if (reconfiguredSerializer is not null)
{
diff --git a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
index 869ee2715e2..06b87d17c5d 100644
--- a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
+++ b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
@@ -22,24 +22,24 @@ internal static class SerializerConfigurator
{
/// Reconfigures a serializer using the specified method if the result of is true or the function is null.
/// If the serializer implements and either:
- /// - is true;
+ /// - is false;
/// - or is a serializer;
/// the method traverses and applies the reconfiguration to its child serializers recursively.
internal static IBsonSerializer ReconfigureSerializer(IBsonSerializer serializer, Func reconfigure,
- Func testFunction = null, bool shouldApplyToCollections = true)
+ Func testFunction = null, bool topLevelOnly = false)
{
switch (serializer)
{
case TSerializer typedSerializer when testFunction?.Invoke(serializer) ?? true:
return reconfigure(typedSerializer);
- case IMultipleChildrenSerializerConfigurableSerializer multipleChildrenSerializerConfigurable:
+ case IMultipleChildrenSerializerConfigurableSerializer multipleChildrenSerializerConfigurable when !topLevelOnly:
{
var newSerializers = new List();
foreach (var childSerializer in multipleChildrenSerializerConfigurable.ChildrenSerializers)
{
var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunction,
- shouldApplyToCollections);
+ false);
newSerializers.Add(reconfiguredChildSerializer ?? childSerializer);
}
@@ -47,10 +47,10 @@ internal static IBsonSerializer ReconfigureSerializer(IBsonSerializ
return multipleChildrenSerializerConfigurable.WithChildrenSerializers(newSerializers.ToArray());
}
case IChildSerializerConfigurable childSerializerConfigurable when
- shouldApplyToCollections || Nullable.GetUnderlyingType(serializer.ValueType) != null:
+ !topLevelOnly || Nullable.GetUnderlyingType(serializer.ValueType) != null:
{
var childSerializer = childSerializerConfigurable.ChildSerializer;
- var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunction, shouldApplyToCollections);
+ var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunction, topLevelOnly);
return reconfiguredChildSerializer != null? childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer) : null;
}
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index 1454d2ba26a..66ab2980093 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -79,7 +79,7 @@ public void Apply_should_configure_serializer_when_member_is_a_nullable_enum(Bso
[InlineData(BsonType.String)]
public void Apply_should_configure_serializer_when_member_is_an_enum_collection(BsonType representation)
{
- var subject = new EnumRepresentationConvention(representation, true);
+ var subject = new EnumRepresentationConvention(representation, false);
var memberMap = CreateMemberMap(c => c.ArrayEnum);
subject.Apply(memberMap);
@@ -95,7 +95,7 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_collection(
[InlineData(BsonType.String)]
public void Apply_should_configure_serializer_when_member_is_a_nested_enum_collection(BsonType representation)
{
- var subject = new EnumRepresentationConvention(representation, true);
+ var subject = new EnumRepresentationConvention(representation, false);
var memberMap = CreateMemberMap(c => c.ArrayOfArrayEnum);
subject.Apply(memberMap);
@@ -111,7 +111,7 @@ public void Apply_should_configure_serializer_when_member_is_a_nested_enum_colle
[InlineData(BsonType.String)]
public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary(BsonType representation)
{
- var subject = new EnumRepresentationConvention(representation, true);
+ var subject = new EnumRepresentationConvention(representation, false);
var memberMap = CreateMemberMap(c => c.DictionaryEnum);
subject.Apply(memberMap);
@@ -127,7 +127,7 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary(
[InlineData(BsonType.String)]
public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary_key(BsonType representation)
{
- var subject = new EnumRepresentationConvention(representation, true);
+ var subject = new EnumRepresentationConvention(representation, false);
var memberMap = CreateMemberMap(c => c.DictionaryKeyEnum);
subject.Apply(memberMap);
@@ -143,7 +143,7 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary_
[InlineData(BsonType.String)]
public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary_value(BsonType representation)
{
- var subject = new EnumRepresentationConvention(representation, true);
+ var subject = new EnumRepresentationConvention(representation, false);
var memberMap = CreateMemberMap(c => c.NestedDictionaryEnum);
subject.Apply(memberMap);
@@ -156,9 +156,9 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary_
[Theory]
[InlineData(BsonType.Int64)]
[InlineData(BsonType.String)]
- public void Apply_should_do_nothing_when_member_is_an_enum_collection_and_should_apply_to_collection_is_false(BsonType representation)
+ public void Apply_should_do_nothing_when_member_is_an_enum_collection_and_top_level_only_is_true(BsonType representation)
{
- var subject = new EnumRepresentationConvention(representation, false);
+ var subject = new EnumRepresentationConvention(representation, true);
var memberMap = CreateMemberMap(c => c.ArrayEnum);
subject.Apply(memberMap);
@@ -220,12 +220,12 @@ public void constructor_with_representation_should_return_expected_result(BsonTy
[ParameterAttributeData]
public void constructor_with_representation_and_should_apply_to_collection_should_return_expected_result(
[Values((BsonType)0, BsonType.Int32, BsonType.Int64, BsonType.String)] BsonType representation,
- [Values(true, false)] bool shouldApplyToCollections)
+ [Values(true, false)] bool topLevelOnly)
{
- var subject = new EnumRepresentationConvention(representation, shouldApplyToCollections);
+ var subject = new EnumRepresentationConvention(representation, topLevelOnly);
subject.Representation.Should().Be(representation);
- subject.ShouldApplyToCollections.Should().Be(shouldApplyToCollections);
+ subject.TopLevelOnly.Should().Be(topLevelOnly);
}
[Theory]
From e86f3fa5487a565d4ea5c33761d86d8fce3f6a12 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Mon, 23 Dec 2024 09:36:11 +0100
Subject: [PATCH 13/19] Removed unnecessary
---
.../Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs b/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs
index ac7be35e386..34ed457ddd8 100644
--- a/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs
+++ b/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs
@@ -61,7 +61,7 @@ public BsonDateOnlyOptionsAttribute(BsonType representation, DateOnlyDocumentFor
/// A reconfigured serializer.
protected override IBsonSerializer Apply(IBsonSerializer serializer)
{
- var reconfiguredSerializer = SerializerConfigurator.ReconfigureSerializer(serializer, (DateOnlySerializer s) => s.WithRepresentation(_representation, _documentFormat), topLevelOnly: false);
+ var reconfiguredSerializer = SerializerConfigurator.ReconfigureSerializer(serializer, (DateOnlySerializer s) => s.WithRepresentation(_representation, _documentFormat));
return reconfiguredSerializer ?? base.Apply(serializer);
}
}
From 2d1132179e6d45d73af9fa17b75489eeafb2782f Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Mon, 23 Dec 2024 09:44:00 +0100
Subject: [PATCH 14/19] Corrected grammar
---
....cs => IMultipleChildSerializerConfigurable.cs} | 14 +++++++-------
.../Serialization/SerializerConfigurator.cs | 6 +++---
.../DictionaryInterfaceImplementerSerializer.cs | 12 ++++++------
...OnlyDictionaryInterfaceImplementerSerializer.cs | 6 +++---
.../EnumRepresentationConventionTests.cs | 4 ++--
5 files changed, 21 insertions(+), 21 deletions(-)
rename src/MongoDB.Bson/Serialization/{IMultipleChildrenSerializerConfigurableSerializer.cs => IMultipleChildSerializerConfigurable.cs} (66%)
diff --git a/src/MongoDB.Bson/Serialization/IMultipleChildrenSerializerConfigurableSerializer.cs b/src/MongoDB.Bson/Serialization/IMultipleChildSerializerConfigurable.cs
similarity index 66%
rename from src/MongoDB.Bson/Serialization/IMultipleChildrenSerializerConfigurableSerializer.cs
rename to src/MongoDB.Bson/Serialization/IMultipleChildSerializerConfigurable.cs
index b73fb2d76c2..187401430fb 100644
--- a/src/MongoDB.Bson/Serialization/IMultipleChildrenSerializerConfigurableSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/IMultipleChildSerializerConfigurable.cs
@@ -16,23 +16,23 @@
namespace MongoDB.Bson.Serialization
{
///
- /// Represents a serializer that has multiple children serializers that configuration attributes can be forwarded to.
+ /// Represents a serializer that has multiple child serializers that configuration attributes can be forwarded to.
///
- public interface IMultipleChildrenSerializerConfigurableSerializer
+ public interface IMultipleChildSerializerConfigurable
{
///
- /// Gets the children serializers.
+ /// Gets the child serializers.
///
///
/// The children serializers.
///
- IBsonSerializer[] ChildrenSerializers { get; }
+ IBsonSerializer[] ChildSerializers { get; }
///
- /// Returns a serializer that has been reconfigured with the specified children serializers.
+ /// Returns a serializer that has been reconfigured with the specified child serializers.
///
- /// The children serializers.
+ /// The child serializers.
/// The reconfigured serializer.
- IBsonSerializer WithChildrenSerializers(IBsonSerializer[] childrenSerializers);
+ IBsonSerializer WithChildSerializers(IBsonSerializer[] childrenSerializers);
}
}
\ No newline at end of file
diff --git a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
index 06b87d17c5d..2c0c9d8711a 100644
--- a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
+++ b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
@@ -32,11 +32,11 @@ internal static IBsonSerializer ReconfigureSerializer(IBsonSerializ
{
case TSerializer typedSerializer when testFunction?.Invoke(serializer) ?? true:
return reconfigure(typedSerializer);
- case IMultipleChildrenSerializerConfigurableSerializer multipleChildrenSerializerConfigurable when !topLevelOnly:
+ case IMultipleChildSerializerConfigurable multipleChildrenSerializerConfigurable when !topLevelOnly:
{
var newSerializers = new List();
- foreach (var childSerializer in multipleChildrenSerializerConfigurable.ChildrenSerializers)
+ foreach (var childSerializer in multipleChildrenSerializerConfigurable.ChildSerializers)
{
var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunction,
false);
@@ -44,7 +44,7 @@ internal static IBsonSerializer ReconfigureSerializer(IBsonSerializ
newSerializers.Add(reconfiguredChildSerializer ?? childSerializer);
}
- return multipleChildrenSerializerConfigurable.WithChildrenSerializers(newSerializers.ToArray());
+ return multipleChildrenSerializerConfigurable.WithChildSerializers(newSerializers.ToArray());
}
case IChildSerializerConfigurable childSerializerConfigurable when
!topLevelOnly || Nullable.GetUnderlyingType(serializer.ValueType) != null:
diff --git a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
index cee58b8f9e3..574290b21f4 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
@@ -27,7 +27,7 @@ namespace MongoDB.Bson.Serialization.Serializers
public sealed class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
- IMultipleChildrenSerializerConfigurableSerializer,
+ IMultipleChildSerializerConfigurable,
IDictionaryRepresentationConfigurable
where TDictionary : class, IDictionary, new()
{
@@ -155,9 +155,9 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
- IBsonSerializer[] IMultipleChildrenSerializerConfigurableSerializer.ChildrenSerializers => [KeySerializer, ValueSerializer];
+ IBsonSerializer[] IMultipleChildSerializerConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
- IBsonSerializer IMultipleChildrenSerializerConfigurableSerializer.WithChildrenSerializers(IBsonSerializer[] childrenSerializers)
+ IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childrenSerializers)
{
if (childrenSerializers.Length != 2)
{
@@ -183,7 +183,7 @@ IBsonSerializer IMultipleChildrenSerializerConfigurableSerializer.WithChildrenSe
public class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
- IMultipleChildrenSerializerConfigurableSerializer,
+ IMultipleChildSerializerConfigurable,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IDictionary
{
@@ -301,9 +301,9 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
- IBsonSerializer[] IMultipleChildrenSerializerConfigurableSerializer.ChildrenSerializers => [KeySerializer, ValueSerializer];
+ IBsonSerializer[] IMultipleChildSerializerConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
- IBsonSerializer IMultipleChildrenSerializerConfigurableSerializer.WithChildrenSerializers(IBsonSerializer[] childrenSerializers)
+ IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childrenSerializers)
{
if (childrenSerializers.Length != 2)
{
diff --git a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
index 436e1de10b4..9f7ac8e027d 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
@@ -28,7 +28,7 @@ namespace MongoDB.Bson.Serialization.Serializers
public sealed class ReadOnlyDictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
- IMultipleChildrenSerializerConfigurableSerializer,
+ IMultipleChildSerializerConfigurable,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IReadOnlyDictionary
{
@@ -123,9 +123,9 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
- IBsonSerializer[] IMultipleChildrenSerializerConfigurableSerializer.ChildrenSerializers => [KeySerializer, ValueSerializer];
+ IBsonSerializer[] IMultipleChildSerializerConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
- IBsonSerializer IMultipleChildrenSerializerConfigurableSerializer.WithChildrenSerializers(IBsonSerializer[] childrenSerializers)
+ IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childrenSerializers)
{
if (childrenSerializers.Length != 2)
{
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index 66ab2980093..2fc4b783ac2 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -132,8 +132,8 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary_
subject.Apply(memberMap);
- var serializer = (IMultipleChildrenSerializerConfigurableSerializer)memberMap.GetSerializer();
- var childSerializer = (EnumSerializer)serializer.ChildrenSerializers[0];
+ var serializer = (IMultipleChildSerializerConfigurable)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)serializer.ChildSerializers[0];
childSerializer.Representation.Should().Be(representation);
}
From 5234bdb4e59de47bdb0111f3917233794ae1fe8d Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Mon, 23 Dec 2024 09:45:01 +0100
Subject: [PATCH 15/19] Grammar corrections
---
src/MongoDB.Bson/Serialization/SerializerConfigurator.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
index 2c0c9d8711a..de07deb9f50 100644
--- a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
+++ b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
@@ -32,11 +32,11 @@ internal static IBsonSerializer ReconfigureSerializer(IBsonSerializ
{
case TSerializer typedSerializer when testFunction?.Invoke(serializer) ?? true:
return reconfigure(typedSerializer);
- case IMultipleChildSerializerConfigurable multipleChildrenSerializerConfigurable when !topLevelOnly:
+ case IMultipleChildSerializerConfigurable multipleChildSerializerConfigurable when !topLevelOnly:
{
var newSerializers = new List();
- foreach (var childSerializer in multipleChildrenSerializerConfigurable.ChildSerializers)
+ foreach (var childSerializer in multipleChildSerializerConfigurable.ChildSerializers)
{
var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunction,
false);
@@ -44,7 +44,7 @@ internal static IBsonSerializer ReconfigureSerializer(IBsonSerializ
newSerializers.Add(reconfiguredChildSerializer ?? childSerializer);
}
- return multipleChildrenSerializerConfigurable.WithChildSerializers(newSerializers.ToArray());
+ return multipleChildSerializerConfigurable.WithChildSerializers(newSerializers.ToArray());
}
case IChildSerializerConfigurable childSerializerConfigurable when
!topLevelOnly || Nullable.GetUnderlyingType(serializer.ValueType) != null:
From 1f0041f3117658a5da14c06362503a96f3d67617 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Mon, 23 Dec 2024 09:56:51 +0100
Subject: [PATCH 16/19] Corrections
---
.../IMultipleChildSerializerConfigurable.cs | 6 +++---
.../DictionaryInterfaceImplementerSerializer.cs | 16 ++++++++--------
...lyDictionaryInterfaceImplementerSerializer.cs | 8 ++++----
3 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/IMultipleChildSerializerConfigurable.cs b/src/MongoDB.Bson/Serialization/IMultipleChildSerializerConfigurable.cs
index 187401430fb..efb5a91455c 100644
--- a/src/MongoDB.Bson/Serialization/IMultipleChildSerializerConfigurable.cs
+++ b/src/MongoDB.Bson/Serialization/IMultipleChildSerializerConfigurable.cs
@@ -24,15 +24,15 @@ public interface IMultipleChildSerializerConfigurable
/// Gets the child serializers.
///
///
- /// The children serializers.
+ /// The child serializers.
///
IBsonSerializer[] ChildSerializers { get; }
///
/// Returns a serializer that has been reconfigured with the specified child serializers.
///
- /// The child serializers.
+ /// The child serializers.
/// The reconfigured serializer.
- IBsonSerializer WithChildSerializers(IBsonSerializer[] childrenSerializers);
+ IBsonSerializer WithChildSerializers(IBsonSerializer[] childSerializers);
}
}
\ No newline at end of file
diff --git a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
index 574290b21f4..15ec6bfa8c0 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
@@ -157,15 +157,15 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
IBsonSerializer[] IMultipleChildSerializerConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
- IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childrenSerializers)
+ IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
{
- if (childrenSerializers.Length != 2)
+ if (childSerializers.Length != 2)
{
throw new Exception("Wrong number of children serializers passed.");
}
- var newKeySerializer = childrenSerializers[0];
- var newValueSerializer = childrenSerializers[1];
+ var newKeySerializer = childSerializers[0];
+ var newValueSerializer = childSerializers[1];
return newKeySerializer.Equals(KeySerializer) && newValueSerializer.Equals(ValueSerializer)
? this
@@ -303,15 +303,15 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
IBsonSerializer[] IMultipleChildSerializerConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
- IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childrenSerializers)
+ IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
{
- if (childrenSerializers.Length != 2)
+ if (childSerializers.Length != 2)
{
throw new Exception("Wrong number of children serializers passed.");
}
- var newKeySerializer = (IBsonSerializer)childrenSerializers[0];
- var newValueSerializer = (IBsonSerializer)childrenSerializers[1];
+ var newKeySerializer = (IBsonSerializer)childSerializers[0];
+ var newValueSerializer = (IBsonSerializer)childSerializers[1];
return newKeySerializer.Equals(KeySerializer) && newValueSerializer.Equals(ValueSerializer)
? this
diff --git a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
index 9f7ac8e027d..43407f2c126 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
@@ -125,15 +125,15 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
IBsonSerializer[] IMultipleChildSerializerConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
- IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childrenSerializers)
+ IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
{
- if (childrenSerializers.Length != 2)
+ if (childSerializers.Length != 2)
{
throw new Exception("Wrong number of children serializers passed.");
}
- var newKeySerializer = (IBsonSerializer)childrenSerializers[0];
- var newValueSerializer = (IBsonSerializer)childrenSerializers[1];
+ var newKeySerializer = (IBsonSerializer)childSerializers[0];
+ var newValueSerializer = (IBsonSerializer)childSerializers[1];
return newKeySerializer.Equals(KeySerializer) && newValueSerializer.Equals(ValueSerializer)
? this
From 38d35f4f38b683edfeae858bc0312963f0cd4369 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Mon, 23 Dec 2024 10:05:13 +0100
Subject: [PATCH 17/19] Correction
---
.../Serializers/DictionaryInterfaceImplementerSerializer.cs | 4 ++--
.../ReadOnlyDictionaryInterfaceImplementerSerializer.cs | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
index 15ec6bfa8c0..93532cba6a4 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
@@ -161,7 +161,7 @@ IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonS
{
if (childSerializers.Length != 2)
{
- throw new Exception("Wrong number of children serializers passed.");
+ throw new Exception("Wrong number of child serializers passed.");
}
var newKeySerializer = childSerializers[0];
@@ -307,7 +307,7 @@ IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonS
{
if (childSerializers.Length != 2)
{
- throw new Exception("Wrong number of children serializers passed.");
+ throw new Exception("Wrong number of child serializers passed.");
}
var newKeySerializer = (IBsonSerializer)childSerializers[0];
diff --git a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
index 43407f2c126..ed7ef4ef502 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
@@ -129,7 +129,7 @@ IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonS
{
if (childSerializers.Length != 2)
{
- throw new Exception("Wrong number of children serializers passed.");
+ throw new Exception("Wrong number of child serializers passed.");
}
var newKeySerializer = (IBsonSerializer)childSerializers[0];
From 0d117d0a72dc9c048ae5dfef98178980255b624e Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Tue, 31 Dec 2024 11:29:04 +0100
Subject: [PATCH 18/19] Simplified reconfigure serializer method and final
corrections Co-authored-by: rstam
---
.../BsonDateOnlyOptionsAttribute.cs | 6 ++-
.../EnumRepresentationConvention.cs | 11 ++++--
... IMultipleChildSerializersConfigurable.cs} | 2 +-
.../Serialization/SerializerConfigurator.cs | 39 +++++++++----------
...ictionaryInterfaceImplementerSerializer.cs | 12 +++---
...ictionaryInterfaceImplementerSerializer.cs | 6 +--
.../EnumRepresentationConventionTests.cs | 2 +-
.../Serializers/DateOnlySerializerTests.cs | 6 ++-
8 files changed, 45 insertions(+), 39 deletions(-)
rename src/MongoDB.Bson/Serialization/{IMultipleChildSerializerConfigurable.cs => IMultipleChildSerializersConfigurable.cs} (95%)
diff --git a/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs b/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs
index 34ed457ddd8..351a8fa121f 100644
--- a/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs
+++ b/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs
@@ -61,8 +61,10 @@ public BsonDateOnlyOptionsAttribute(BsonType representation, DateOnlyDocumentFor
/// A reconfigured serializer.
protected override IBsonSerializer Apply(IBsonSerializer serializer)
{
- var reconfiguredSerializer = SerializerConfigurator.ReconfigureSerializer(serializer, (DateOnlySerializer s) => s.WithRepresentation(_representation, _documentFormat));
- return reconfiguredSerializer ?? base.Apply(serializer);
+ return SerializerConfigurator.ReconfigureSerializerRecursively(serializer, Reconfigure) ?? base.Apply(serializer);
+
+ IBsonSerializer Reconfigure(IBsonSerializer s)
+ => s is DateOnlySerializer dos ? dos.WithRepresentation(_representation, _documentFormat) : null;
}
}
#endif
diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index ca7dabd4afc..840d7c7191f 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -67,15 +67,18 @@ public EnumRepresentationConvention(BsonType representation, bool topLevelOnly)
/// The member map.
public void Apply(BsonMemberMap memberMap)
{
- var reconfiguredSerializer =
- SerializerConfigurator.ReconfigureSerializer(memberMap.GetSerializer(),
- s => s.WithRepresentation(_representation),
- s => s.ValueType.IsEnum, _topLevelOnly);
+ var serializer = memberMap.GetSerializer();
+ var reconfiguredSerializer = _topLevelOnly && Nullable.GetUnderlyingType(serializer.ValueType) == null ?
+ Reconfigure(serializer) :
+ SerializerConfigurator.ReconfigureSerializerRecursively(serializer, Reconfigure);
if (reconfiguredSerializer is not null)
{
memberMap.SetSerializer(reconfiguredSerializer);
}
+
+ IBsonSerializer Reconfigure(IBsonSerializer s)
+ => s.ValueType.IsEnum ? (s as IRepresentationConfigurable)?.WithRepresentation(_representation) : null;
}
// private methods
diff --git a/src/MongoDB.Bson/Serialization/IMultipleChildSerializerConfigurable.cs b/src/MongoDB.Bson/Serialization/IMultipleChildSerializersConfigurable.cs
similarity index 95%
rename from src/MongoDB.Bson/Serialization/IMultipleChildSerializerConfigurable.cs
rename to src/MongoDB.Bson/Serialization/IMultipleChildSerializersConfigurable.cs
index efb5a91455c..4c9a858ba8a 100644
--- a/src/MongoDB.Bson/Serialization/IMultipleChildSerializerConfigurable.cs
+++ b/src/MongoDB.Bson/Serialization/IMultipleChildSerializersConfigurable.cs
@@ -18,7 +18,7 @@ namespace MongoDB.Bson.Serialization
///
/// Represents a serializer that has multiple child serializers that configuration attributes can be forwarded to.
///
- public interface IMultipleChildSerializerConfigurable
+ public interface IMultipleChildSerializersConfigurable
{
///
/// Gets the child serializers.
diff --git a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
index de07deb9f50..d02062a1a4e 100644
--- a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
+++ b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
@@ -20,42 +20,39 @@ namespace MongoDB.Bson.Serialization
{
internal static class SerializerConfigurator
{
- /// Reconfigures a serializer using the specified method if the result of is true or the function is null.
- /// If the serializer implements and either:
- /// - is false;
- /// - or is a serializer;
- /// the method traverses and applies the reconfiguration to its child serializers recursively.
- internal static IBsonSerializer ReconfigureSerializer(IBsonSerializer serializer, Func reconfigure,
- Func testFunction = null, bool topLevelOnly = false)
+ // Reconfigures a serializer recursively.
+ // The reconfigure Func should return null if it does not apply to a given serializer.
+ internal static IBsonSerializer ReconfigureSerializerRecursively(
+ IBsonSerializer serializer,
+ Func reconfigure)
{
switch (serializer)
{
- case TSerializer typedSerializer when testFunction?.Invoke(serializer) ?? true:
- return reconfigure(typedSerializer);
- case IMultipleChildSerializerConfigurable multipleChildSerializerConfigurable when !topLevelOnly:
+ // check IMultipleChildSerializersConfigurableSerializer first because some serializers implement both interfaces
+ case IMultipleChildSerializersConfigurable multipleChildSerializerConfigurable:
{
- var newSerializers = new List();
+ var anyChildSerializerWasReconfigured = false;
+ var reconfiguredChildSerializers = new List();
foreach (var childSerializer in multipleChildSerializerConfigurable.ChildSerializers)
{
- var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunction,
- false);
-
- newSerializers.Add(reconfiguredChildSerializer ?? childSerializer);
+ var reconfiguredChildSerializer = ReconfigureSerializerRecursively(childSerializer, reconfigure);
+ anyChildSerializerWasReconfigured |= reconfiguredChildSerializer != null;
+ reconfiguredChildSerializers.Add(reconfiguredChildSerializer ?? childSerializer);
}
- return multipleChildSerializerConfigurable.WithChildSerializers(newSerializers.ToArray());
+ return anyChildSerializerWasReconfigured ? multipleChildSerializerConfigurable.WithChildSerializers(reconfiguredChildSerializers.ToArray()) : null;
}
- case IChildSerializerConfigurable childSerializerConfigurable when
- !topLevelOnly || Nullable.GetUnderlyingType(serializer.ValueType) != null:
+
+ case IChildSerializerConfigurable childSerializerConfigurable:
{
var childSerializer = childSerializerConfigurable.ChildSerializer;
- var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure, testFunction, topLevelOnly);
- return reconfiguredChildSerializer != null? childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer) : null;
+ var reconfiguredChildSerializer = ReconfigureSerializerRecursively(childSerializer, reconfigure);
+ return reconfiguredChildSerializer != null ? childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer) : null;
}
default:
- return null;
+ return reconfigure(serializer);
}
}
}
diff --git a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
index 93532cba6a4..59e6cb42365 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
@@ -27,7 +27,7 @@ namespace MongoDB.Bson.Serialization.Serializers
public sealed class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
- IMultipleChildSerializerConfigurable,
+ IMultipleChildSerializersConfigurable,
IDictionaryRepresentationConfigurable
where TDictionary : class, IDictionary, new()
{
@@ -155,9 +155,9 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
- IBsonSerializer[] IMultipleChildSerializerConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
+ IBsonSerializer[] IMultipleChildSerializersConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
- IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
+ IBsonSerializer IMultipleChildSerializersConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
{
if (childSerializers.Length != 2)
{
@@ -183,7 +183,7 @@ IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonS
public class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
- IMultipleChildSerializerConfigurable,
+ IMultipleChildSerializersConfigurable,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IDictionary
{
@@ -301,9 +301,9 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
- IBsonSerializer[] IMultipleChildSerializerConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
+ IBsonSerializer[] IMultipleChildSerializersConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
- IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
+ IBsonSerializer IMultipleChildSerializersConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
{
if (childSerializers.Length != 2)
{
diff --git a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
index ed7ef4ef502..4d522ca580d 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
@@ -28,7 +28,7 @@ namespace MongoDB.Bson.Serialization.Serializers
public sealed class ReadOnlyDictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
- IMultipleChildSerializerConfigurable,
+ IMultipleChildSerializersConfigurable,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IReadOnlyDictionary
{
@@ -123,9 +123,9 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
- IBsonSerializer[] IMultipleChildSerializerConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
+ IBsonSerializer[] IMultipleChildSerializersConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
- IBsonSerializer IMultipleChildSerializerConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
+ IBsonSerializer IMultipleChildSerializersConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
{
if (childSerializers.Length != 2)
{
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index 2fc4b783ac2..bdba3f1d33d 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -132,7 +132,7 @@ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary_
subject.Apply(memberMap);
- var serializer = (IMultipleChildSerializerConfigurable)memberMap.GetSerializer();
+ var serializer = (IMultipleChildSerializersConfigurable)memberMap.GetSerializer();
var childSerializer = (EnumSerializer)serializer.ChildSerializers[0];
childSerializer.Representation.Should().Be(representation);
}
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Serializers/DateOnlySerializerTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Serializers/DateOnlySerializerTests.cs
index 76b1159261c..e4c4eb50e91 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Serializers/DateOnlySerializerTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Serializers/DateOnlySerializerTests.cs
@@ -40,12 +40,13 @@ public void Attribute_should_set_correct_format()
DateTimeTicksFormat = dateOnly,
YearMonthDayFormat = dateOnly,
IgnoredFormat = dateOnly,
+ NullableYearMonthDayFormat = dateOnly,
ArrayYearMonthDayFormat = [dateOnly, dateOnly]
};
var json = testObj.ToJson();
const string expected = """
- { "DateTimeTicksFormat" : { "DateTime" : { "$date" : "2024-10-05T00:00:00Z" }, "Ticks" : 638636832000000000 }, "YearMonthDayFormat" : { "Year" : 2024, "Month" : 10, "Day" : 5 }, "IgnoredFormat" : 638636832000000000, "ArrayYearMonthDayFormat" : [{ "Year" : 2024, "Month" : 10, "Day" : 5 }, { "Year" : 2024, "Month" : 10, "Day" : 5 }] }
+ { "DateTimeTicksFormat" : { "DateTime" : { "$date" : "2024-10-05T00:00:00Z" }, "Ticks" : 638636832000000000 }, "YearMonthDayFormat" : { "Year" : 2024, "Month" : 10, "Day" : 5 }, "IgnoredFormat" : 638636832000000000, "NullableYearMonthDayFormat" : { "Year" : 2024, "Month" : 10, "Day" : 5 }, "ArrayYearMonthDayFormat" : [{ "Year" : 2024, "Month" : 10, "Day" : 5 }, { "Year" : 2024, "Month" : 10, "Day" : 5 }] }
""";
Assert.Equal(expected, json);
}
@@ -366,6 +367,9 @@ private class TestClass
[BsonDateOnlyOptions(BsonType.Int64, DateOnlyDocumentFormat.YearMonthDay)]
public DateOnly IgnoredFormat { get; set; }
+ [BsonDateOnlyOptions(BsonType.Document, DateOnlyDocumentFormat.YearMonthDay)]
+ public DateOnly? NullableYearMonthDayFormat { get; set; }
+
[BsonDateOnlyOptions(BsonType.Document, DateOnlyDocumentFormat.YearMonthDay)]
public DateOnly[] ArrayYearMonthDayFormat { get; set; }
}
From c2711c3df5fb655053334f8de66980628f8293cc Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Tue, 31 Dec 2024 18:59:14 +0100
Subject: [PATCH 19/19] Fixed nullable check
---
.../Conventions/EnumRepresentationConvention.cs | 2 +-
src/MongoDB.Bson/Serialization/TypeExtensions.cs | 12 ++++++++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index 840d7c7191f..a57fa18ac5e 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -68,7 +68,7 @@ public EnumRepresentationConvention(BsonType representation, bool topLevelOnly)
public void Apply(BsonMemberMap memberMap)
{
var serializer = memberMap.GetSerializer();
- var reconfiguredSerializer = _topLevelOnly && Nullable.GetUnderlyingType(serializer.ValueType) == null ?
+ var reconfiguredSerializer = _topLevelOnly && !serializer.ValueType.IsNullableEnum() ?
Reconfigure(serializer) :
SerializerConfigurator.ReconfigureSerializerRecursively(serializer, Reconfigure);
diff --git a/src/MongoDB.Bson/Serialization/TypeExtensions.cs b/src/MongoDB.Bson/Serialization/TypeExtensions.cs
index 04f533ede95..83e7c48d205 100644
--- a/src/MongoDB.Bson/Serialization/TypeExtensions.cs
+++ b/src/MongoDB.Bson/Serialization/TypeExtensions.cs
@@ -29,5 +29,17 @@ public static bool IsAnonymousType(this Type type)
type.IsGenericType &&
type.Name.Contains("Anon"); // don't check for more than "Anon" so it works in mono also
}
+
+ public static bool IsNullable(this Type type)
+ {
+ return type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
+ }
+
+ public static bool IsNullableEnum(this Type type)
+ {
+ return
+ type.IsNullable() &&
+ Nullable.GetUnderlyingType(type).IsEnum;
+ }
}
}