diff --git a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
index e7f46a8e566..30e6dc50007 100644
--- a/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
+++ b/src/MongoDB.Bson/Serialization/Conventions/EnumRepresentationConvention.cs
@@ -50,49 +50,65 @@ public EnumRepresentationConvention(BsonType representation)
/// The member map.
public void Apply(BsonMemberMap memberMap)
{
- var memberType = memberMap.MemberType;
- var memberTypeInfo = memberType.GetTypeInfo();
+ var serializer = memberMap.GetSerializer();
+ var reconfiguredSerializer = Apply(serializer);
+ if (reconfiguredSerializer != null)
+ {
+ memberMap.SetSerializer(reconfiguredSerializer);
+ }
+ }
+
+ private IBsonSerializer Apply(IBsonSerializer serializer)
+ {
+#if NETSTANDARD1_5 || NETSTANDARD1_6
+ var type = serializer.ValueType.GetTypeInfo();
+#else
+ var type = serializer.ValueType;
+#endif
- if (memberTypeInfo.IsEnum)
+ if (type.IsEnum)
{
- var serializer = memberMap.GetSerializer();
var representationConfigurableSerializer = serializer as IRepresentationConfigurable;
if (representationConfigurableSerializer != null)
{
var reconfiguredSerializer = representationConfigurableSerializer.WithRepresentation(_representation);
- memberMap.SetSerializer(reconfiguredSerializer);
+ return reconfiguredSerializer;
}
- return;
}
-
- if (IsNullableEnum(memberType))
+ // order matters
+ var childSerializersConfigurableSerializer = serializer as IChildSerializersConfigurable;
+ if (childSerializersConfigurableSerializer != null)
+ {
+ var childSerializers = childSerializersConfigurableSerializer.ChildSerializers;
+ for (int i = 0; i < childSerializers.Count; i++)
+ {
+ var reconfiguredChildSerializer = Apply(childSerializers[i]);
+ if (reconfiguredChildSerializer != null)
+ {
+ var reconfiguredSerializer = childSerializersConfigurableSerializer.WithChildSerializer(i, reconfiguredChildSerializer);
+ return reconfiguredSerializer;
+ }
+ }
+ }
+ else
{
- 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 = Apply(childSerializer);
+ if (reconfiguredChildSerializer != null)
{
- var reconfiguredChildSerializer = representationConfigurableChildSerializer.WithRepresentation(_representation);
var reconfiguredSerializer = childSerializerConfigurableSerializer.WithChildSerializer(reconfiguredChildSerializer);
- memberMap.SetSerializer(reconfiguredSerializer);
+ return reconfiguredSerializer;
}
}
- return;
}
- }
- // private methods
- private bool IsNullableEnum(Type type)
- {
- return
- type.GetTypeInfo().IsGenericType &&
- type.GetGenericTypeDefinition() == typeof(Nullable<>) &&
- Nullable.GetUnderlyingType(type).GetTypeInfo().IsEnum;
+ return null;
}
+ // private methods
private void EnsureRepresentationIsValidForEnums(BsonType representation)
{
if (
diff --git a/src/MongoDB.Bson/Serialization/IChildSerializersConfigurable.cs b/src/MongoDB.Bson/Serialization/IChildSerializersConfigurable.cs
new file mode 100644
index 00000000000..e07f2dabe6b
--- /dev/null
+++ b/src/MongoDB.Bson/Serialization/IChildSerializersConfigurable.cs
@@ -0,0 +1,46 @@
+/* Copyright 2010-2014 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.
+*/
+
+using System.Collections.Generic;
+
+namespace MongoDB.Bson.Serialization
+{
+ // this interface is public so custom serializers with several child serializers can choose to implement it
+ // but typically you would choose to implement this interface explicitly
+ // these methods support forwarding attributes to child serializers and wouldn't normally be public
+
+ ///
+ /// Represents a serializer that has multiple child serializers that configuration attributes can be forwarded to.
+ /// Each child serializer gets identified by an index.
+ ///
+ public interface IChildSerializersConfigurable
+ {
+ ///
+ /// Gets the child serializer.
+ ///
+ ///
+ /// The child serializer.
+ ///
+ IList ChildSerializers { get; }
+
+ ///
+ /// Returns a serializer that has been reconfigured with the specified child serializer.
+ ///
+ /// The index of the child serializer.
+ /// The child serializer.
+ /// The reconfigured serializer.
+ IBsonSerializer WithChildSerializer(int serializerIndex, IBsonSerializer childSerializer);
+ }
+}
diff --git a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
index caef5cb6ae6..2ca2c34ad07 100644
--- a/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
+++ b/src/MongoDB.Bson/Serialization/Serializers/DictionaryInterfaceImplementerSerializer.cs
@@ -28,6 +28,7 @@ namespace MongoDB.Bson.Serialization.Serializers
public class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
+ IChildSerializersConfigurable,
IDictionaryRepresentationConfigurable
where TDictionary : class, IDictionary, new()
{
@@ -154,6 +155,31 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
{
return WithDictionaryRepresentation(dictionaryRepresentation);
}
+
+ IList IChildSerializersConfigurable.ChildSerializers
+ {
+ get
+ {
+ return new[]
+ {
+ KeySerializer,
+ ValueSerializer,
+ };
+ }
+ }
+
+ IBsonSerializer IChildSerializersConfigurable.WithChildSerializer(int serializerIndex, IBsonSerializer childSerializer)
+ {
+ switch (serializerIndex)
+ {
+ case 0:
+ return WithKeySerializer(childSerializer);
+ case 1:
+ return WithValueSerializer(childSerializer);
+ }
+
+ return null;
+ }
}
///
@@ -165,6 +191,7 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
public class DictionaryInterfaceImplementerSerializer :
DictionarySerializerBase,
IChildSerializerConfigurable,
+ IChildSerializersConfigurable,
IDictionaryRepresentationConfigurable>
where TDictionary : class, IDictionary
{
@@ -281,6 +308,31 @@ IBsonSerializer IDictionaryRepresentationConfigurable.WithDictionaryRepresentati
{
return WithDictionaryRepresentation(dictionaryRepresentation);
}
+
+ IList IChildSerializersConfigurable.ChildSerializers
+ {
+ get
+ {
+ return new IBsonSerializer[]
+ {
+ KeySerializer,
+ ValueSerializer,
+ };
+ }
+ }
+
+ IBsonSerializer IChildSerializersConfigurable.WithChildSerializer(int serializerIndex, IBsonSerializer childSerializer)
+ {
+ switch (serializerIndex)
+ {
+ case 0:
+ return WithKeySerializer((IBsonSerializer) childSerializer);
+ case 1:
+ return WithValueSerializer((IBsonSerializer) childSerializer);
+ }
+
+ return null;
+ }
///
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 b455cb919d1..a4fb96c4425 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;
@@ -32,6 +33,10 @@ public class C
public E E { get; set; }
public E? NE { get; set; }
public int I { get; set; }
+ public List L { get; set; }
+ public List>> L3 { get; set; }
+ public Dictionary DK { get; set; }
+ public Dictionary DV { get; set; }
}
[Theory]
@@ -48,7 +53,6 @@ public void Apply_should_configure_serializer_when_member_is_an_enum(BsonType re
serializer.Representation.Should().Be(representation);
}
-
[Theory]
[InlineData(BsonType.Int32)]
[InlineData(BsonType.Int64)]
@@ -64,6 +68,64 @@ 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)]
+ public void Apply_should_configure_serializer_when_member_is_a_dictionary_with_enum_keys(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation);
+ var memberMap = CreateMemberMap(c => c.DK);
+
+ subject.Apply(memberMap);
+
+ var serializer = (DictionaryInterfaceImplementerSerializer, E, int>)memberMap.GetSerializer();
+ ((IRepresentationConfigurable)serializer.KeySerializer).Representation.Should().Be(representation);
+ }
+
+ [Theory]
+ [InlineData(BsonType.Int32)]
+ [InlineData(BsonType.Int64)]
+ public void Apply_should_configure_serializer_when_member_is_a_dictionary_with_enum_values(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation);
+ var memberMap = CreateMemberMap(c => c.DV);
+
+ subject.Apply(memberMap);
+
+ var serializer = (DictionaryInterfaceImplementerSerializer, int, E>)memberMap.GetSerializer();
+ ((IRepresentationConfigurable)serializer.ValueSerializer).Representation.Should().Be(representation);
+ }
+
+ [Theory]
+ [InlineData(BsonType.Int32)]
+ [InlineData(BsonType.Int64)]
+ public void Apply_should_configure_serializer_when_member_is_a_collection_of_enums(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation);
+ var memberMap = CreateMemberMap(c => c.L);
+
+ subject.Apply(memberMap);
+
+ var serializer = (EnumerableInterfaceImplementerSerializer, E>)memberMap.GetSerializer();
+ ((IRepresentationConfigurable)serializer.ItemSerializer).Representation.Should().Be(representation);
+ }
+
+ [Theory]
+ [InlineData(BsonType.Int32)]
+ [InlineData(BsonType.Int64)]
+ public void Apply_should_configure_serializer_when_member_is_a_nested_collection_of_enums(BsonType representation)
+ {
+ var subject = new EnumRepresentationConvention(representation);
+ var memberMap = CreateMemberMap(c => c.L3);
+
+ subject.Apply(memberMap);
+
+ var serializer = (IChildSerializerConfigurable)memberMap.GetSerializer();
+ serializer = (IChildSerializerConfigurable)serializer.ChildSerializer;
+ var childSerializer = (EnumerableInterfaceImplementerSerializer, E>)serializer.ChildSerializer;
+ ((IRepresentationConfigurable)childSerializer.ItemSerializer).Representation.Should().Be(representation);
+ }
+
[Fact]
public void Apply_should_do_nothing_when_member_is_not_an_enum()
{