Skip to content

Commit ceac8f7

Browse files
committed
CSHARP-1884: Make In filter method changes backward compatible.
1 parent 3be268e commit ceac8f7

File tree

4 files changed

+61
-11
lines changed

4 files changed

+61
-11
lines changed

src/MongoDB.Driver/FieldValueSerializerHelper.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public static IBsonSerializer GetSerializerForValueType(IBsonSerializer fieldSer
5959
}
6060

6161
// synthesize an EnumConvertingSerializer using the field serializer
62-
if (fieldTypeInfo.IsEnum)
62+
if (fieldTypeInfo.IsEnum && valueType.IsConvertibleToEnum())
6363
{
6464
var enumConvertingSerializerType = typeof(EnumConvertingSerializer<,>).MakeGenericType(valueType, fieldType);
6565
var enumConvertingSerializerConstructor = enumConvertingSerializerType.GetTypeInfo().GetConstructor(new[] { fieldSerializerInterfaceType });
@@ -95,17 +95,15 @@ public static IBsonSerializer GetSerializerForValueType(IBsonSerializer fieldSer
9595
return (IBsonSerializer)ienumerableSerializerConstructor.Invoke(new object[] { itemSerializer });
9696
}
9797

98-
// use the item serializer if fieldSerializer is an IBsonArraySerializer of valueType items
98+
// if the fieldSerializer is an array serializer try to adapt its itemSerializer for valueType
9999
IBsonArraySerializer arraySerializer;
100100
if ((arraySerializer = fieldSerializer as IBsonArraySerializer) != null)
101101
{
102102
BsonSerializationInfo itemSerializationInfo;
103103
if (arraySerializer.TryGetItemSerializationInfo(out itemSerializationInfo))
104104
{
105-
if (itemSerializationInfo.Serializer.ValueType == valueType)
106-
{
107-
return itemSerializationInfo.Serializer;
108-
}
105+
var itemSerializer = itemSerializationInfo.Serializer;
106+
return GetSerializerForValueType(itemSerializer, valueType);
109107
}
110108
}
111109

src/MongoDB.Driver/FilterDefinitionBuilder.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,8 +1585,8 @@ public override BsonDocument Render(IBsonSerializer<TDocument> documentSerialize
15851585
{
15861586
var renderedField = _field.Render(documentSerializer, serializerRegistry);
15871587

1588-
IBsonSerializer itemSerializer;
1589-
if (renderedField.FieldSerializer != null)
1588+
IBsonSerializer itemSerializer = null;
1589+
if (itemSerializer == null && renderedField.FieldSerializer != null)
15901590
{
15911591
var arraySerializer = renderedField.FieldSerializer as IBsonArraySerializer;
15921592
BsonSerializationInfo itemSerializationInfo;
@@ -1595,9 +1595,9 @@ public override BsonDocument Render(IBsonSerializer<TDocument> documentSerialize
15951595
var message = string.Format("The serializer for field '{0}' must implement IBsonArraySerializer and provide item serialization info.", renderedField.FieldName);
15961596
throw new InvalidOperationException(message);
15971597
}
1598-
itemSerializer = itemSerializationInfo.Serializer;
1598+
itemSerializer = FieldValueSerializerHelper.GetSerializerForValueType(itemSerializationInfo.Serializer, typeof(TItem));
15991599
}
1600-
else
1600+
if (itemSerializer == null)
16011601
{
16021602
itemSerializer = serializerRegistry.GetSerializer<TItem>();
16031603
}

src/MongoDB.Driver/Support/ReflectionExtensions.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2015-2016 MongoDB Inc.
1+
/* Copyright 2015-2017 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -74,6 +74,20 @@ public static bool IsNumeric(this Type type)
7474
type == typeof(Decimal128);
7575
}
7676

77+
public static bool IsConvertibleToEnum(this Type type)
78+
{
79+
return
80+
type == typeof(sbyte) ||
81+
type == typeof(short) ||
82+
type == typeof(int) ||
83+
type == typeof(long) ||
84+
type == typeof(byte) ||
85+
type == typeof(ushort) ||
86+
type == typeof(uint) ||
87+
type == typeof(ulong) ||
88+
type == typeof(Enum);
89+
}
90+
7791
public static Type GetNullableUnderlyingType(this Type type)
7892
{
7993
if (!IsNullable(type))

tests/MongoDB.Driver.Tests/FilterDefinitionBuilderTests.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,33 @@ public void In_Typed()
491491
Assert(subject.AnyIn("FavoriteColors", new[] { "blue", "green" }), "{colors: {$in: ['blue','green']}}");
492492
}
493493

494+
[Fact]
495+
public void In_with_enum()
496+
{
497+
var subject = CreateSubject<BsonDocument>();
498+
499+
Assert(subject.In("E", new[] { EnumForClassWithEnums.A, EnumForClassWithEnums.B }), "{ E : { $in : [ 0, 1 ] } }");
500+
Assert(subject.AnyIn("A", new[] { EnumForClassWithEnums.A, EnumForClassWithEnums.B }), "{ A : { $in : [ 0, 1 ] } }");
501+
}
502+
503+
[Fact]
504+
public void In_typed_with_enum()
505+
{
506+
var subject = CreateSubject<ClassWithEnums>();
507+
508+
Assert(subject.In("E", new[] { 0, 1 }), "{ E : { $in : [ \"A\", \"B\" ] } }");
509+
Assert(subject.In("A", new[] { 0, 1 }), "{ A : { $in : [ \"A\", \"B\" ] } }");
510+
Assert(subject.AnyIn("A", new[] { 0, 1 }), "{ A : { $in : [ \"A\", \"B\" ] } }");
511+
512+
Assert(subject.In("E", new[] { "A", "B" }), "{ E : { $in : [ \"A\", \"B\" ] } }");
513+
Assert(subject.In("A", new[] { "A", "B" }), "{ A : { $in : [ \"A\", \"B\" ] } }");
514+
Assert(subject.AnyIn("A", new[] { "A", "B" }), "{ A : { $in : [ \"A\", \"B\" ] } }");
515+
516+
Assert(subject.In("E", new[] { EnumForClassWithEnums.A, EnumForClassWithEnums.B }), "{ E : { $in : [ \"A\", \"B\" ] } }");
517+
Assert(subject.In("A", new[] { EnumForClassWithEnums.A, EnumForClassWithEnums.B }), "{ A : { $in : [ \"A\", \"B\" ] } }");
518+
Assert(subject.AnyIn("A", new[] { EnumForClassWithEnums.A, EnumForClassWithEnums.B }), "{ A : { $in : [ \"A\", \"B\" ] } }");
519+
}
520+
494521
[Fact]
495522
public void Lt()
496523
{
@@ -985,6 +1012,17 @@ private FilterDefinitionBuilder<TDocument> CreateSubject<TDocument>()
9851012
return new FilterDefinitionBuilder<TDocument>();
9861013
}
9871014

1015+
private enum EnumForClassWithEnums { A, B }
1016+
1017+
private class ClassWithEnums
1018+
{
1019+
public int Id { get; set; }
1020+
[BsonRepresentation(BsonType.String)]
1021+
public EnumForClassWithEnums E { get; set; }
1022+
[BsonRepresentation(BsonType.String)]
1023+
public EnumForClassWithEnums[] A { get; set; }
1024+
}
1025+
9881026
private class Person
9891027
{
9901028
[BsonElement("fn")]

0 commit comments

Comments
 (0)