diff --git a/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs b/src/MongoDB.Bson/Serialization/Attributes/BsonDateOnlyOptionsAttribute.cs
index 34ed457ddd..351a8fa121 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 55ad9a00b9..a57fa18ac5 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
{
@@ -25,6 +24,7 @@ public class EnumRepresentationConvention : ConventionBase, IMemberMapConvention
{
// private fields
private readonly BsonType _representation;
+ private readonly bool _topLevelOnly;
// constructors
///
@@ -33,9 +33,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, true)
+ {
+ }
+
+ ///
+ /// 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 only to top level enum properties, and not collections of enums, for example.
+ public EnumRepresentationConvention(BsonType representation, bool topLevelOnly)
{
EnsureRepresentationIsValidForEnums(representation);
_representation = representation;
+ _topLevelOnly = topLevelOnly;
}
///
@@ -43,66 +55,40 @@ public EnumRepresentationConvention(BsonType representation)
///
public BsonType Representation => _representation;
+ ///
+ /// 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 TopLevelOnly => _topLevelOnly;
+
///
/// Applies a modification to the member map.
///
/// The member map.
public void Apply(BsonMemberMap memberMap)
{
- var memberType = memberMap.MemberType;
- var memberTypeInfo = memberType.GetTypeInfo();
+ var serializer = memberMap.GetSerializer();
+ var reconfiguredSerializer = _topLevelOnly && !serializer.ValueType.IsNullableEnum() ?
+ Reconfigure(serializer) :
+ SerializerConfigurator.ReconfigureSerializerRecursively(serializer, Reconfigure);
- if (memberTypeInfo.IsEnum)
+ if (reconfiguredSerializer is not null)
{
- var serializer = memberMap.GetSerializer();
- var representationConfigurableSerializer = serializer as IRepresentationConfigurable;
- if (representationConfigurableSerializer != null)
- {
- var reconfiguredSerializer = representationConfigurableSerializer.WithRepresentation(_representation);
- memberMap.SetSerializer(reconfiguredSerializer);
- }
- return;
+ memberMap.SetSerializer(reconfiguredSerializer);
}
- if (IsNullableEnum(memberType))
- {
- 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;
- }
+ IBsonSerializer Reconfigure(IBsonSerializer s)
+ => s.ValueType.IsEnum ? (s as IRepresentationConfigurable)?.WithRepresentation(_representation) : null;
}
// 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/src/MongoDB.Bson/Serialization/IMultipleChildSerializersConfigurable.cs b/src/MongoDB.Bson/Serialization/IMultipleChildSerializersConfigurable.cs
new file mode 100644
index 0000000000..4c9a858ba8
--- /dev/null
+++ b/src/MongoDB.Bson/Serialization/IMultipleChildSerializersConfigurable.cs
@@ -0,0 +1,38 @@
+/* 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 multiple child serializers that configuration attributes can be forwarded to.
+ ///
+ public interface IMultipleChildSerializersConfigurable
+ {
+ ///
+ /// Gets the child serializers.
+ ///
+ ///
+ /// The child serializers.
+ ///
+ IBsonSerializer[] ChildSerializers { get; }
+
+ ///
+ /// Returns a serializer that has been reconfigured with the specified child serializers.
+ ///
+ /// The child serializers.
+ /// The reconfigured serializer.
+ IBsonSerializer WithChildSerializers(IBsonSerializer[] childSerializers);
+ }
+}
\ No newline at end of file
diff --git a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
index 7e1cfbecbe..d02062a1a4 100644
--- a/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
+++ b/src/MongoDB.Bson/Serialization/SerializerConfigurator.cs
@@ -14,36 +14,45 @@
*/
using System;
+using System.Collections.Generic;
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.
- /// 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)
+ // 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)
{
+ // check IMultipleChildSerializersConfigurableSerializer first because some serializers implement both interfaces
+ case IMultipleChildSerializersConfigurable multipleChildSerializerConfigurable:
+ {
+ var anyChildSerializerWasReconfigured = false;
+ var reconfiguredChildSerializers = new List();
+
+ foreach (var childSerializer in multipleChildSerializerConfigurable.ChildSerializers)
+ {
+ var reconfiguredChildSerializer = ReconfigureSerializerRecursively(childSerializer, reconfigure);
+ anyChildSerializerWasReconfigured |= reconfiguredChildSerializer != null;
+ reconfiguredChildSerializers.Add(reconfiguredChildSerializer ?? childSerializer);
+ }
+
+ return anyChildSerializerWasReconfigured ? multipleChildSerializerConfigurable.WithChildSerializers(reconfiguredChildSerializers.ToArray()) : null;
+ }
+
case IChildSerializerConfigurable childSerializerConfigurable:
+ {
var childSerializer = childSerializerConfigurable.ChildSerializer;
- var reconfiguredChildSerializer = ReconfigureSerializer(childSerializer, reconfigure);
- return reconfiguredChildSerializer != null? childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer) : null;
-
- case TSerializer typedSerializer:
- return reconfigure(typedSerializer);
+ 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 d188eb1c9f..59e6cb4236 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,
+ IMultipleChildSerializersConfigurable,
IDictionaryRepresentationConfigurable
where TDictionary : class, IDictionary, new()
{
@@ -153,6 +154,24 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
{
return WithDictionaryRepresentation(dictionaryRepresentation);
}
+
+ IBsonSerializer[] IMultipleChildSerializersConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
+
+ IBsonSerializer IMultipleChildSerializersConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
+ {
+ if (childSerializers.Length != 2)
+ {
+ throw new Exception("Wrong number of child serializers passed.");
+ }
+
+ var newKeySerializer = childSerializers[0];
+ var newValueSerializer = childSerializers[1];
+
+ return newKeySerializer.Equals(KeySerializer) && newValueSerializer.Equals(ValueSerializer)
+ ? this
+ : new DictionaryInterfaceImplementerSerializer(DictionaryRepresentation, newKeySerializer,
+ newValueSerializer);
+ }
}
///
@@ -164,6 +183,7 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
public class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
+ IMultipleChildSerializersConfigurable,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IDictionary
{
@@ -281,6 +301,24 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
+ IBsonSerializer[] IMultipleChildSerializersConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
+
+ IBsonSerializer IMultipleChildSerializersConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
+ {
+ if (childSerializers.Length != 2)
+ {
+ throw new Exception("Wrong number of child serializers passed.");
+ }
+
+ var newKeySerializer = (IBsonSerializer)childSerializers[0];
+ var newValueSerializer = (IBsonSerializer)childSerializers[1];
+
+ return newKeySerializer.Equals(KeySerializer) && newValueSerializer.Equals(ValueSerializer)
+ ? this
+ : new DictionaryInterfaceImplementerSerializer(DictionaryRepresentation, newKeySerializer,
+ newValueSerializer);
+ }
+
///
protected override ICollection> CreateAccumulator()
{
diff --git a/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ReadOnlyDictionaryInterfaceImplementerSerializer.cs
index ae2b747922..4d522ca580 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,
+ IMultipleChildSerializersConfigurable,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IReadOnlyDictionary
{
@@ -122,6 +123,24 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
return WithDictionaryRepresentation(dictionaryRepresentation);
}
+ IBsonSerializer[] IMultipleChildSerializersConfigurable.ChildSerializers => [KeySerializer, ValueSerializer];
+
+ IBsonSerializer IMultipleChildSerializersConfigurable.WithChildSerializers(IBsonSerializer[] childSerializers)
+ {
+ if (childSerializers.Length != 2)
+ {
+ throw new Exception("Wrong number of child serializers passed.");
+ }
+
+ var newKeySerializer = (IBsonSerializer)childSerializers[0];
+ var newValueSerializer = (IBsonSerializer)childSerializers[1];
+
+ return newKeySerializer.Equals(KeySerializer) && newValueSerializer.Equals(ValueSerializer)
+ ? this
+ : new ReadOnlyDictionaryInterfaceImplementerSerializer(DictionaryRepresentation, newKeySerializer,
+ newValueSerializer);
+ }
+
///
protected override ICollection> CreateAccumulator()
{
diff --git a/src/MongoDB.Bson/Serialization/TypeExtensions.cs b/src/MongoDB.Bson/Serialization/TypeExtensions.cs
index 04f533ede9..83e7c48d20 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;
+ }
}
}
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
index bde58d6af7..bdba3f1d33 100644
--- a/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
+++ b/tests/MongoDB.Bson.Tests/Serialization/Conventions/EnumRepresentationConventionTests.cs
@@ -14,11 +14,13 @@
*/
using System;
+using System.Collections.Generic;
using System.Linq.Expressions;
using FluentAssertions;
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
@@ -31,7 +33,14 @@ 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 Dictionary DictionaryKeyEnum { get; set; }
public int I { get; set; }
+ public int NI { get; set; }
+ public int[] ArrayInt { get; set; }
}
[Theory]
@@ -51,6 +60,7 @@ public void Apply_should_configure_serializer_when_member_is_an_enum(BsonType re
[Theory]
[InlineData(BsonType.Int32)]
[InlineData(BsonType.Int64)]
+ [InlineData(BsonType.String)]
public void Apply_should_configure_serializer_when_member_is_a_nullable_enum(BsonType representation)
{
var subject = new EnumRepresentationConvention(representation);
@@ -63,6 +73,101 @@ 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, false);
+ var memberMap = CreateMemberMap(c => c.ArrayEnum);
+
+ subject.Apply(memberMap);
+
+ var serializer = (IChildSerializerConfigurable)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)serializer.ChildSerializer;
+ 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, false);
+ 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)]
+ [InlineData(BsonType.String)]
+ public void Apply_should_configure_serializer_when_member_is_an_enum_dictionary(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation, false);
+ var memberMap = CreateMemberMap(c => c.DictionaryEnum);
+
+ subject.Apply(memberMap);
+
+ var serializer = (IChildSerializerConfigurable)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)serializer.ChildSerializer;
+ 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, false);
+ var memberMap = CreateMemberMap(c => c.DictionaryKeyEnum);
+
+ subject.Apply(memberMap);
+
+ var serializer = (IMultipleChildSerializersConfigurable)memberMap.GetSerializer();
+ var childSerializer = (EnumSerializer)serializer.ChildSerializers[0];
+ 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_value(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation, false);
+ 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);
+ }
+
+ [Theory]
+ [InlineData(BsonType.Int64)]
+ [InlineData(BsonType.String)]
+ 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, true);
+ 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()
{
@@ -75,18 +180,54 @@ 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()
+ {
+ 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)]
[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 topLevelOnly)
+ {
+ var subject = new EnumRepresentationConvention(representation, topLevelOnly);
+
+ subject.Representation.Should().Be(representation);
+ subject.TopLevelOnly.Should().Be(topLevelOnly);
+ }
+
[Theory]
[InlineData(BsonType.Decimal128)]
[InlineData(BsonType.Double)]
diff --git a/tests/MongoDB.Bson.Tests/Serialization/Serializers/DateOnlySerializerTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Serializers/DateOnlySerializerTests.cs
index 76b1159261..e4c4eb50e9 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; }
}